mirror of
git://git.sv.gnu.org/emacs.git
synced 2025-12-23 22:20:24 -08:00
; Merge from https://github.com/jwiegley/use-package
This commit is contained in:
commit
4a1e9d61b5
16 changed files with 6562 additions and 0 deletions
946
doc/misc/use-package.texi
Normal file
946
doc/misc/use-package.texi
Normal file
|
|
@ -0,0 +1,946 @@
|
|||
\input texinfo @c -*- texinfo -*-
|
||||
@c %**start of header
|
||||
@setfilename use-package.info
|
||||
@settitle use-package User Manual
|
||||
@documentencoding UTF-8
|
||||
@documentlanguage en
|
||||
@c %**end of header
|
||||
|
||||
@copying
|
||||
@quotation
|
||||
Copyright (C) 2012-2022 Free Software Foundation, Inc.
|
||||
|
||||
You can redistribute this document and/or modify it under the terms
|
||||
of the GNU General Public License as published by the Free Software
|
||||
Foundation, either version 3 of the License, or (at your option) any
|
||||
later version.
|
||||
|
||||
This document 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.
|
||||
|
||||
@end quotation
|
||||
@end copying
|
||||
|
||||
@dircategory Emacs
|
||||
@direntry
|
||||
* use-package: (use-package). Declarative package configuration for Emacs.
|
||||
@end direntry
|
||||
|
||||
@finalout
|
||||
@titlepage
|
||||
@title use-package User Manual
|
||||
@subtitle for version 2.4.1-119-g0be480e+1
|
||||
@author John Wiegley
|
||||
@page
|
||||
@vskip 0pt plus 1filll
|
||||
@insertcopying
|
||||
@end titlepage
|
||||
|
||||
@contents
|
||||
|
||||
@ifnottex
|
||||
@node Top
|
||||
@top use-package User Manual
|
||||
|
||||
The @code{use-package} macro allows you to isolate package configuration in your
|
||||
@code{.emacs} file in a way that is both performance-oriented and, well, 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
|
||||
around 2 seconds, with no loss of functionality!
|
||||
|
||||
@insertcopying
|
||||
@end ifnottex
|
||||
|
||||
@menu
|
||||
* Introduction::
|
||||
* Installation::
|
||||
* Getting Started::
|
||||
* Basic Concepts::
|
||||
* Issues/Requests::
|
||||
* Keywords::
|
||||
* Debugging Tools::
|
||||
|
||||
@detailmenu
|
||||
--- The Detailed Node Listing ---
|
||||
|
||||
Installation
|
||||
|
||||
* Installing from GNU ELPA::
|
||||
* Installing from the Git Repository::
|
||||
* Post-Installation Tasks::
|
||||
|
||||
Keywords
|
||||
|
||||
* @code{after}:: @code{:after}.
|
||||
* @code{bind-keymap} @code{bind-keymap*}:: @code{:bind-keymap}, @code{:bind-keymap*}.
|
||||
* @code{bind} @code{bind*}:: @code{:bind}, @code{:bind*}.
|
||||
* @code{commands}:: @code{:commands}.
|
||||
* @code{preface} @code{init} @code{config}:: @code{:preface}, @code{:init}, @code{:config}.
|
||||
* @code{custom}:: @code{:custom}.
|
||||
* @code{custom-face}:: @code{:custom-face}.
|
||||
* @code{defer} @code{demand}:: @code{:defer}, @code{:demand}.
|
||||
* @code{defines} @code{functions}:: @code{:defines}, @code{:functions}.
|
||||
* @code{diminish} @code{delight}:: @code{:diminish}, @code{:delight}.
|
||||
* @code{disabled}:: @code{:disabled}.
|
||||
* @code{ensure} @code{pin}:: @code{:ensure}, @code{:pin}.
|
||||
* @code{hook}:: @code{:hook}.
|
||||
* @code{if} @code{when} @code{unless}:: @code{:if}, @code{:when}, @code{:unless}.
|
||||
* @code{load-path}:: @code{:load-path}.
|
||||
* @code{mode} @code{interpreter}:: @code{:mode}, @code{:interpreter}.
|
||||
* @code{magic} @code{magic-fallback}:: @code{:magic}, @code{:magic-fallback}.
|
||||
* @code{no-require}:: @code{:no-require}.
|
||||
* @code{requires}:: @code{:requires}.
|
||||
|
||||
@code{bind}, @code{bind*}
|
||||
|
||||
* Binding to local keymaps::
|
||||
|
||||
|
||||
@end detailmenu
|
||||
@end menu
|
||||
|
||||
@node Introduction
|
||||
@chapter Introduction
|
||||
|
||||
The @code{use-package} macro allows you to isolate package configuration in your
|
||||
@code{.emacs} file in a way that is both performance-oriented and, well, 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
|
||||
around 2 seconds, with no loss of functionality!
|
||||
|
||||
More text to come@dots{}
|
||||
|
||||
@node Installation
|
||||
@chapter Installation
|
||||
|
||||
use-package can be installed using Emacs' package manager or manually from
|
||||
its development repository.
|
||||
|
||||
@menu
|
||||
* Installing from GNU ELPA::
|
||||
* Installing from the Git Repository::
|
||||
* Post-Installation Tasks::
|
||||
@end menu
|
||||
|
||||
@node Installing from GNU ELPA
|
||||
@section Installing from GNU ELPA
|
||||
|
||||
use-package is available from GNU ELPA. If you haven't used
|
||||
Emacs' package manager before, then it is high time you familiarize yourself
|
||||
with it by reading the documentation in the Emacs manual, see
|
||||
@ref{Packages,,,emacs,}. Then add one of the archives to @code{package-archives}:
|
||||
|
||||
First, you need to update the local package list using:
|
||||
|
||||
@example
|
||||
M-x package-refresh-contents RET
|
||||
@end example
|
||||
|
||||
Once you have done that, you can install use-package and its
|
||||
dependencies using:
|
||||
|
||||
@example
|
||||
M-x package-install RET use-package RET
|
||||
@end example
|
||||
|
||||
Now see @ref{Post-Installation Tasks}.
|
||||
|
||||
@node Installing from the Git Repository
|
||||
@section Installing from the Git Repository
|
||||
|
||||
First, use Git to clone the use-package repository:
|
||||
|
||||
@example
|
||||
$ git clone https://github.com/jwiegley/use-package.git ~/.emacs.d/site-lisp/use-package
|
||||
$ cd ~/.emacs.d/site-lisp/use-package
|
||||
@end example
|
||||
|
||||
Then compile the libraries and generate the info manuals:
|
||||
|
||||
@example
|
||||
$ make
|
||||
@end example
|
||||
|
||||
You may need to create @code{/path/to/use-package/config.mk} with the following
|
||||
content before running @code{make}:
|
||||
|
||||
@example
|
||||
LOAD_PATH = -L /path/to/use-package
|
||||
@end example
|
||||
|
||||
Finally add this to your init file:
|
||||
|
||||
@lisp
|
||||
(add-to-list 'load-path "~/.emacs.d/site-lisp/use-package")
|
||||
(require 'use-package)
|
||||
|
||||
(with-eval-after-load 'info
|
||||
(info-initialize)
|
||||
(add-to-list 'Info-directory-list
|
||||
"~/.emacs.d/site-lisp/use-package/"))
|
||||
@end lisp
|
||||
|
||||
Note that elements of @code{load-path} should not end with a slash, while those of
|
||||
@code{Info-directory-list} should.
|
||||
|
||||
Instead of running use-package directly from the repository by adding it to
|
||||
the @code{load-path}, you might want to instead install it in some other directory
|
||||
using @code{sudo make install} and setting @code{load-path} accordingly.
|
||||
|
||||
To update use-package use:
|
||||
|
||||
@example
|
||||
$ git pull
|
||||
$ make
|
||||
@end example
|
||||
|
||||
At times it might be necessary to run @code{make clean all} instead.
|
||||
|
||||
To view all available targets use @code{make help}.
|
||||
|
||||
Now see @ref{Post-Installation Tasks}.
|
||||
|
||||
@node Post-Installation Tasks
|
||||
@section Post-Installation Tasks
|
||||
|
||||
After installing use-package you should verify that you are indeed using the
|
||||
use-package release you think you are using. It's best to restart Emacs before
|
||||
doing so, to make sure you are not using an outdated value for @code{load-path}.
|
||||
|
||||
@example
|
||||
C-h v use-package-version RET
|
||||
@end example
|
||||
|
||||
should display something like
|
||||
|
||||
@example
|
||||
use-package-version’s value is "2.4.3"
|
||||
@end example
|
||||
|
||||
If you are completely new to use-package then see @ref{Getting Started}.
|
||||
|
||||
If you run into problems, then please see the @ref{Debugging Tools}.
|
||||
|
||||
@node Getting Started
|
||||
@chapter Getting Started
|
||||
|
||||
TODO@. For now, see @code{README.md}.
|
||||
|
||||
@node Basic Concepts
|
||||
@chapter Basic Concepts
|
||||
|
||||
@code{use-package} was created for few basic reasons, each of which drove the
|
||||
design in various ways. Understanding these reasons may help make some of
|
||||
those decisions clearer:
|
||||
|
||||
@itemize
|
||||
@item
|
||||
To gather all configuration details of a package into one place,
|
||||
making it easier to copy, disable, or move it elsewhere in the init
|
||||
file.
|
||||
|
||||
@item
|
||||
To reduce duplication and boilerplate, capturing several common
|
||||
practices as mere keywords both easy and intuitive to use.
|
||||
|
||||
@item
|
||||
To make startup time of Emacs as quick as possible, without
|
||||
sacrificing the quantity of add-on packages used.
|
||||
|
||||
@item
|
||||
To make it so errors encountered during startup disable only the
|
||||
package raising the error, and as little else as possible, leaving a
|
||||
close to a functional Emacs as possible.
|
||||
|
||||
@item
|
||||
To allow byte-compilation of one's init file so that any warnings or
|
||||
errors seen are meaningful. In this way, even if byte-compilation is not
|
||||
used for speed (reason 3), it can still be used as a sanity check.
|
||||
@end itemize
|
||||
|
||||
@node Issues/Requests
|
||||
@chapter Issues/Requests
|
||||
|
||||
@node Keywords
|
||||
@chapter Keywords
|
||||
|
||||
@menu
|
||||
* @code{after}:: @code{after}.
|
||||
* @code{bind-keymap} @code{bind-keymap*}:: @code{:bind-keymap}, @code{:bind-keymap*}.
|
||||
* @code{bind} @code{bind*}:: @code{bind} @code{:bind*}.
|
||||
* @code{commands}:: @code{:commands}.
|
||||
* @code{preface} @code{init} @code{config}:: @code{:preface}, @code{:init}, @code{:config}.
|
||||
* @code{custom}:: @code{:custom}.
|
||||
* @code{custom-face}:: @code{:custom-face}.
|
||||
* @code{defer} @code{demand}:: @code{:defer}, @code{:demand}.
|
||||
* @code{defines} @code{functions}:: @code{:defines}, @code{:functions}.
|
||||
* @code{diminish} @code{delight}:: @code{:diminish}, @code{:delight}.
|
||||
* @code{disabled}:: @code{:disabled}.
|
||||
* @code{ensure} @code{pin}:: @code{:ensure}, @code{:pin}.
|
||||
* @code{hook}:: @code{:hook}.
|
||||
* @code{if} @code{when} @code{unless}:: @code{:if}, @code{:when}, @code{:unless}.
|
||||
* @code{load-path}:: @code{:load-path}.
|
||||
* @code{mode} @code{interpreter}:: @code{:mode}, @code{:interpreter}.
|
||||
* @code{magic} @code{magic-fallback}:: @code{:magic}, @code{:magic-fallback}.
|
||||
* @code{no-require}:: @code{:no-require}.
|
||||
* @code{requires}:: @code{:requires}.
|
||||
@end menu
|
||||
|
||||
@node @code{after}
|
||||
@section @code{:after}
|
||||
|
||||
Sometimes it only makes sense to configure a package after another has been
|
||||
loaded, because certain variables or functions are not in scope until that
|
||||
time. This can achieved using an @code{:after} keyword that allows a fairly rich
|
||||
description of the exact conditions when loading should occur. Here is an
|
||||
example:
|
||||
|
||||
@lisp
|
||||
(use-package hydra
|
||||
:load-path "site-lisp/hydra")
|
||||
|
||||
(use-package ivy
|
||||
:load-path "site-lisp/swiper")
|
||||
|
||||
(use-package ivy-hydra
|
||||
:after (ivy hydra))
|
||||
@end lisp
|
||||
|
||||
In this case, because all of these packages are demand-loaded in the order
|
||||
they occur, the use of @code{:after} is not strictly necessary. By using it,
|
||||
however, the above code becomes order-independent, without an implicit
|
||||
depedence on the nature of your init file.
|
||||
|
||||
By default, @code{:after (foo bar)} is the same as @code{:after (:all foo bar)}, meaning
|
||||
that loading of the given package will not happen until both @code{foo} and @code{bar}
|
||||
have been loaded. Here are some of the other possibilities:
|
||||
|
||||
@lisp
|
||||
:after (foo bar)
|
||||
:after (:all foo bar)
|
||||
:after (:any foo bar)
|
||||
:after (:all (:any foo bar) (:any baz quux))
|
||||
:after (:any (:all foo bar) (:all baz quux))
|
||||
@end lisp
|
||||
|
||||
When you nest selectors, such as @code{(:any (:all foo bar) (:all baz quux))}, it
|
||||
means that the package will be loaded when either both @code{foo} and @code{bar} have
|
||||
been loaded, or both @code{baz} and @code{quux} have been loaded.
|
||||
|
||||
@strong{NOTE}: Pay attention if you set @code{use-package-always-defer} to t, and also use
|
||||
the @code{:after} keyword, as you will need to specify how the declared package is
|
||||
to be loaded: e.g., by some @code{:bind}. If you're not using one of the mechanisms
|
||||
that registers autoloads, such as @code{:bind} or @code{:hook}, and your package manager
|
||||
does not provide autoloads, it's possible that without adding @code{:demand t} to
|
||||
those declarations, your package will never be loaded.
|
||||
|
||||
@node @code{bind-keymap} @code{bind-keymap*}
|
||||
@section @code{:bind-keymap}, @code{:bind-keymap*}
|
||||
|
||||
Normally @code{:bind} expects that commands are functions that will be autoloaded
|
||||
from the given package. However, this does not work if one of those commands
|
||||
is actually a keymap, since keymaps are not functions, and cannot be
|
||||
autoloaded using Emacs' @code{autoload} mechanism.
|
||||
|
||||
To handle this case, @code{use-package} offers a special, limited variant of
|
||||
@code{:bind} called @code{:bind-keymap}. The only difference is that the "commands"
|
||||
bound to by @code{:bind-keymap} must be keymaps defined in the package, rather than
|
||||
command functions. This is handled behind the scenes by generating custom code
|
||||
that loads the package containing the keymap, and then re-executes your
|
||||
keypress after the first load, to reinterpret that keypress as a prefix key.
|
||||
|
||||
For example:
|
||||
|
||||
@lisp
|
||||
(use-package projectile
|
||||
:bind-keymap
|
||||
("C-c p" . projectile-command-map)
|
||||
@end lisp
|
||||
|
||||
@node @code{bind} @code{bind*}
|
||||
@section @code{:bind}, @code{:bind*}
|
||||
|
||||
Another common thing to do when loading a module is to bind a key to primary
|
||||
commands within that module:
|
||||
|
||||
@lisp
|
||||
(use-package ace-jump-mode
|
||||
:bind ("C-." . ace-jump-mode))
|
||||
@end lisp
|
||||
|
||||
This does two things: first, it creates an autoload for the @code{ace-jump-mode}
|
||||
command and defers loading of @code{ace-jump-mode} until you actually use it.
|
||||
Second, it binds the key @code{C-.} to that command. After loading, you can use
|
||||
@code{M-x describe-personal-keybindings} to see all such keybindings you've set
|
||||
throughout your @code{.emacs} file.
|
||||
|
||||
A more literal way to do the exact same thing is:
|
||||
|
||||
@lisp
|
||||
(use-package ace-jump-mode
|
||||
:commands ace-jump-mode
|
||||
:init
|
||||
(bind-key "C-." 'ace-jump-mode))
|
||||
@end lisp
|
||||
|
||||
When you use the @code{:commands} keyword, it creates autoloads for those commands
|
||||
and defers loading of the module until they are used. Since the @code{:init} form
|
||||
is always run---even if @code{ace-jump-mode} might not be on your system---remember
|
||||
to restrict @code{:init} code to only what would succeed either way.
|
||||
|
||||
The @code{:bind} keyword takes either a cons or a list of conses:
|
||||
|
||||
@lisp
|
||||
(use-package hi-lock
|
||||
:bind (("M-o l" . highlight-lines-matching-regexp)
|
||||
("M-o r" . highlight-regexp)
|
||||
("M-o w" . highlight-phrase)))
|
||||
@end lisp
|
||||
|
||||
The @code{:commands} keyword likewise takes either a symbol or a list of symbols.
|
||||
|
||||
NOTE: Special keys like @code{tab} or @code{F1}-@code{Fn} can be written in square brackets,
|
||||
i.e. @code{[tab]} instead of @code{"tab"}. The syntax for the keybindings is similar to
|
||||
the "kbd" syntax: see @uref{https://www.gnu.org/software/emacs/manual/html_node/emacs/Init-Rebinding.html, the Emacs Manual} for more information.
|
||||
|
||||
Examples:
|
||||
|
||||
@lisp
|
||||
(use-package helm
|
||||
:bind (("M-x" . helm-M-x)
|
||||
("M-<f5>" . helm-find-files)
|
||||
([f10] . helm-buffers-list)
|
||||
([S-f10] . helm-recentf)))
|
||||
@end lisp
|
||||
|
||||
@menu
|
||||
* Binding to local keymaps::
|
||||
@end menu
|
||||
|
||||
@node Binding to local keymaps
|
||||
@subsection Binding to local keymaps
|
||||
|
||||
Slightly different from binding a key to a keymap, is binding a key @strong{within} a
|
||||
local keymap that only exists after the package is loaded. @code{use-package}
|
||||
supports this with a @code{:map} modifier, taking the local keymap to bind to:
|
||||
|
||||
@lisp
|
||||
(use-package helm
|
||||
:bind (:map helm-command-map
|
||||
("C-c h" . helm-execute-persistent-action)))
|
||||
@end lisp
|
||||
|
||||
The effect of this statement is to wait until @code{helm} has loaded, and then to
|
||||
bind the key @code{C-c h} to @code{helm-execute-persistent-action} within Helm's local
|
||||
keymap, @code{helm-mode-map}.
|
||||
|
||||
Multiple uses of @code{:map} may be specified. Any binding occurring before the
|
||||
first use of @code{:map} are applied to the global keymap:
|
||||
|
||||
@lisp
|
||||
(use-package term
|
||||
:bind (("C-c t" . term)
|
||||
:map term-mode-map
|
||||
("M-p" . term-send-up)
|
||||
("M-n" . term-send-down)
|
||||
:map term-raw-map
|
||||
("M-o" . other-window)
|
||||
("M-p" . term-send-up)
|
||||
("M-n" . term-send-down)))
|
||||
@end lisp
|
||||
|
||||
@node @code{commands}
|
||||
@section @code{:commands}
|
||||
|
||||
@node @code{preface} @code{init} @code{config}
|
||||
@section @code{:preface}, @code{:init}, @code{:config}
|
||||
|
||||
Here is the simplest @code{use-package} declaration:
|
||||
|
||||
@lisp
|
||||
;; This is only needed once, near the top of the file
|
||||
(eval-when-compile
|
||||
;; Following line is not needed if use-package.el is in ~/.emacs.d
|
||||
(add-to-list 'load-path "<path where use-package is installed>")
|
||||
(require 'use-package))
|
||||
|
||||
(use-package foo)
|
||||
@end lisp
|
||||
|
||||
This loads in the package @code{foo}, but only if @code{foo} is available on your
|
||||
system. If not, a warning is logged to the @code{*Messages*} buffer. If it
|
||||
succeeds, a message about @code{"Loading foo"} is logged, along with the time it
|
||||
took to load, if it took over 0.1 seconds.
|
||||
|
||||
Use the @code{:init} keyword to execute code before a package is loaded. It
|
||||
accepts one or more forms, up until the next keyword:
|
||||
|
||||
@lisp
|
||||
(use-package foo
|
||||
:init
|
||||
(setq foo-variable t))
|
||||
@end lisp
|
||||
|
||||
Similarly, @code{:config} can be used to execute code after a package is loaded.
|
||||
In cases where loading is done lazily (see more about autoloading below), this
|
||||
execution is deferred until after the autoload occurs:
|
||||
|
||||
@lisp
|
||||
(use-package foo
|
||||
:init
|
||||
(setq foo-variable t)
|
||||
:config
|
||||
(foo-mode 1))
|
||||
@end lisp
|
||||
|
||||
As you might expect, you can use @code{:init} and @code{:config} together:
|
||||
|
||||
@lisp
|
||||
(use-package color-moccur
|
||||
:commands (isearch-moccur isearch-all)
|
||||
:bind (("M-s O" . moccur)
|
||||
:map isearch-mode-map
|
||||
("M-o" . isearch-moccur)
|
||||
("M-O" . isearch-moccur-all))
|
||||
:init
|
||||
(setq isearch-lazy-highlight t)
|
||||
:config
|
||||
(use-package moccur-edit))
|
||||
@end lisp
|
||||
|
||||
In this case, I want to autoload the commands @code{isearch-moccur} and
|
||||
@code{isearch-all} from @code{color-moccur.el}, and bind keys both at the global level
|
||||
and within the @code{isearch-mode-map} (see next section). When the package is
|
||||
actually loaded (by using one of these commands), @code{moccur-edit} is also
|
||||
loaded, to allow editing of the @code{moccur} buffer.
|
||||
|
||||
@node @code{custom}
|
||||
@section @code{:custom}
|
||||
|
||||
The @code{:custom} keyword allows customization of package custom variables.
|
||||
|
||||
@lisp
|
||||
(use-package comint
|
||||
:custom
|
||||
(comint-buffer-maximum-size 20000 "Increase comint buffer size.")
|
||||
(comint-prompt-read-only t "Make the prompt read only."))
|
||||
@end lisp
|
||||
|
||||
The documentation string is not mandatory.
|
||||
|
||||
@node @code{custom-face}
|
||||
@section @code{:custom-face}
|
||||
|
||||
The @code{:custom-face} keyword allows customization of package custom faces.
|
||||
|
||||
@lisp
|
||||
(use-package eruby-mode
|
||||
:custom-face
|
||||
(eruby-standard-face ((t (:slant italic)))))
|
||||
@end lisp
|
||||
|
||||
@node @code{defer} @code{demand}
|
||||
@section @code{:defer}, @code{:demand}
|
||||
|
||||
In almost all cases you don't need to manually specify @code{:defer t}. This is
|
||||
implied whenever @code{:bind} or @code{:mode} or @code{:interpreter} is used. Typically, you
|
||||
only need to specify @code{:defer} if you know for a fact that some other package
|
||||
will do something to cause your package to load at the appropriate time, and
|
||||
thus you would like to defer loading even though use-package isn't creating
|
||||
any autoloads for you.
|
||||
|
||||
You can override package deferral with the @code{:demand} keyword. Thus, even if
|
||||
you use @code{:bind}, using @code{:demand} will force loading to occur immediately and
|
||||
not establish an autoload for the bound key.
|
||||
|
||||
@node @code{defines} @code{functions}
|
||||
@section @code{:defines}, @code{:functions}
|
||||
|
||||
Another feature of @code{use-package} is that it always loads every file that it
|
||||
can when @code{.emacs} is being byte-compiled. 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 @code{:defines} and @code{:functions} keywords to introduce dummy variable and
|
||||
function declarations solely for the sake of the byte-compiler:
|
||||
|
||||
@lisp
|
||||
(use-package texinfo
|
||||
:defines texinfo-section-list
|
||||
:commands texinfo-mode
|
||||
:init
|
||||
(add-to-list 'auto-mode-alist '("\\.texi$" . texinfo-mode)))
|
||||
@end lisp
|
||||
|
||||
If you need to silence a missing function warning, you can use @code{:functions}:
|
||||
|
||||
@lisp
|
||||
(use-package ruby-mode
|
||||
:mode "\\.rb\\'"
|
||||
:interpreter "ruby"
|
||||
:functions inf-ruby-keys
|
||||
:config
|
||||
(defun my-ruby-mode-hook ()
|
||||
(require 'inf-ruby)
|
||||
(inf-ruby-keys))
|
||||
|
||||
(add-hook 'ruby-mode-hook 'my-ruby-mode-hook))
|
||||
@end lisp
|
||||
|
||||
@node @code{diminish} @code{delight}
|
||||
@section @code{:diminish}, @code{:delight}
|
||||
|
||||
@code{use-package} also provides built-in support for the diminish and delight
|
||||
utilities---if you have them installed. Their purpose is to remove or change
|
||||
minor mode strings in your mode-line.
|
||||
|
||||
@uref{https://github.com/myrjola/diminish.el, diminish} is invoked with the @code{:diminish} keyword, which is passed either a
|
||||
minor mode symbol, a cons of the symbol and its replacement string, or just a
|
||||
replacement string, in which case the minor mode symbol is guessed to be the
|
||||
package name with "-mode" appended at the end:
|
||||
|
||||
@lisp
|
||||
(use-package abbrev
|
||||
:diminish abbrev-mode
|
||||
:config
|
||||
(if (file-exists-p abbrev-file-name)
|
||||
(quietly-read-abbrev-file)))
|
||||
@end lisp
|
||||
|
||||
@uref{https://elpa.gnu.org/packages/delight.html, delight} is invoked with the @code{:delight} keyword, which is passed a minor mode
|
||||
symbol, a replacement string or quoted @uref{https://www.gnu.org/software/emacs/manual/html_node/elisp/Mode-Line-Data.html, mode-line data} (in which case the minor
|
||||
mode symbol is guessed to be the package name with "-mode" appended at the
|
||||
end), both of these, or several lists of both. If no arguments are provided,
|
||||
the default mode name is hidden completely.
|
||||
|
||||
@lisp
|
||||
;; Don't show anything for rainbow-mode.
|
||||
(use-package rainbow-mode
|
||||
:delight)
|
||||
|
||||
;; Don't show anything for auto-revert-mode, which doesn't match
|
||||
;; its package name.
|
||||
(use-package autorevert
|
||||
:delight auto-revert-mode)
|
||||
|
||||
;; Remove the mode name for projectile-mode, but show the project name.
|
||||
(use-package projectile
|
||||
:delight '(:eval (concat " " (projectile-project-name))))
|
||||
|
||||
;; Completely hide visual-line-mode and change auto-fill-mode to " AF".
|
||||
(use-package emacs
|
||||
:delight
|
||||
(auto-fill-function " AF")
|
||||
(visual-line-mode))
|
||||
@end lisp
|
||||
|
||||
@node @code{disabled}
|
||||
@section @code{:disabled}
|
||||
|
||||
The @code{:disabled} keyword can turn off a module you're having difficulties with,
|
||||
or stop loading something you're not using at the present time:
|
||||
|
||||
@lisp
|
||||
(use-package ess-site
|
||||
:disabled
|
||||
:commands R)
|
||||
@end lisp
|
||||
|
||||
When byte-compiling your @code{.emacs} file, disabled declarations are omitted
|
||||
from the output entirely, to accelerate startup times.
|
||||
|
||||
@node @code{ensure} @code{pin}
|
||||
@section @code{:ensure}, @code{:pin}
|
||||
|
||||
You can use @code{use-package} to load packages from ELPA with @code{package.el}. This
|
||||
is particularly useful if you share your @code{.emacs} among several machines; the
|
||||
relevant packages are downloaded automatically once declared in your @code{.emacs}.
|
||||
The @code{:ensure} keyword causes the package(s) to be installed automatically if
|
||||
not already present on your system (set @code{(setq use-package-always-ensure t)}
|
||||
if you wish this behavior to be global for all packages):
|
||||
|
||||
@lisp
|
||||
(use-package magit
|
||||
:ensure t)
|
||||
@end lisp
|
||||
|
||||
If you need to install a different package from the one named by
|
||||
@code{use-package}, you can specify it like this:
|
||||
|
||||
@lisp
|
||||
(use-package tex
|
||||
:ensure auctex)
|
||||
@end lisp
|
||||
|
||||
Lastly, when running on Emacs 24.4 or later, use-package can pin a package to
|
||||
a specific archive, allowing you to mix and match packages from different
|
||||
archives. The primary use-case for this is preferring packages from the
|
||||
@code{melpa-stable} and @code{gnu} archives, but using specific packages from @code{melpa}
|
||||
when you need to track newer versions than what is available in the @code{stable}
|
||||
archives is also a valid use-case.
|
||||
|
||||
By default @code{package.el} prefers @code{melpa} over @code{melpa-stable} due to the
|
||||
versioning @code{(> evil-20141208.623 evil-1.0.9)}, so even if you are tracking
|
||||
only a single package from @code{melpa}, you will need to tag all the non-@code{melpa}
|
||||
packages with the appropriate archive. If this really annoys you, then you can
|
||||
set @code{use-package-always-pin} to set a default.
|
||||
|
||||
If you want to manually keep a package updated and ignore upstream updates,
|
||||
you can pin it to @code{manual}, which as long as there is no repository by that
|
||||
name, will Just Work(tm).
|
||||
|
||||
@code{use-package} throws an error if you try to pin a package to an archive that
|
||||
has not been configured using @code{package-archives} (apart from the magic
|
||||
@code{manual} archive mentioned above):
|
||||
|
||||
@example
|
||||
Archive 'foo' requested for package 'bar' is not available.
|
||||
@end example
|
||||
|
||||
Example:
|
||||
|
||||
@lisp
|
||||
(use-package company
|
||||
:ensure t
|
||||
:pin melpa-stable)
|
||||
|
||||
(use-package evil
|
||||
:ensure t)
|
||||
;; no :pin needed, as package.el will choose the version in melpa
|
||||
|
||||
(use-package adaptive-wrap
|
||||
:ensure t
|
||||
;; as this package is available only in the gnu archive, this is
|
||||
;; technically not needed, but it helps to highlight where it
|
||||
;; comes from
|
||||
:pin gnu)
|
||||
|
||||
(use-package org
|
||||
:ensure t
|
||||
;; ignore org-mode from upstream and use a manually installed version
|
||||
:pin manual)
|
||||
@end lisp
|
||||
|
||||
@strong{NOTE}: the @code{:pin} argument has no effect on emacs versions < 24.4.
|
||||
|
||||
@node @code{hook}
|
||||
@section @code{:hook}
|
||||
|
||||
The @code{:hook} keyword allows adding functions onto hooks, here only the basename
|
||||
of the hook is required. Thus, all of the following are equivalent:
|
||||
|
||||
@lisp
|
||||
(use-package ace-jump-mode
|
||||
:hook prog-mode)
|
||||
|
||||
(use-package ace-jump-mode
|
||||
:hook (prog-mode . ace-jump-mode))
|
||||
|
||||
(use-package ace-jump-mode
|
||||
:commands ace-jump-mode
|
||||
:init
|
||||
(add-hook 'prog-mode-hook #'ace-jump-mode))
|
||||
@end lisp
|
||||
|
||||
And likewise, when multiple hooks should be applied, the following are also
|
||||
equivalent:
|
||||
|
||||
@lisp
|
||||
(use-package ace-jump-mode
|
||||
:hook (prog-mode text-mode))
|
||||
|
||||
(use-package ace-jump-mode
|
||||
:hook ((prog-mode text-mode) . ace-jump-mode))
|
||||
|
||||
(use-package ace-jump-mode
|
||||
:hook ((prog-mode . ace-jump-mode)
|
||||
(text-mode . ace-jump-mode)))
|
||||
|
||||
(use-package ace-jump-mode
|
||||
:commands ace-jump-mode
|
||||
:init
|
||||
(add-hook 'prog-mode-hook #'ace-jump-mode)
|
||||
(add-hook 'text-mode-hook #'ace-jump-mode))
|
||||
@end lisp
|
||||
|
||||
The use of @code{:hook}, as with @code{:bind}, @code{:mode}, @code{:interpreter}, etc., causes the
|
||||
functions being hooked to implicitly be read as @code{:commands} (meaning they will
|
||||
establish interactive @code{autoload} definitions for that module, if not already
|
||||
defined as functions), and so @code{:defer t} is also implied by @code{:hook}.
|
||||
|
||||
@node @code{if} @code{when} @code{unless}
|
||||
@section @code{:if}, @code{:when}, @code{:unless}
|
||||
|
||||
You can use the @code{:if} keyword to predicate the loading and initialization of
|
||||
modules.
|
||||
|
||||
For example, I only want @code{edit-server} running for my main, graphical Emacs,
|
||||
not for other Emacsen I may start at the command line:
|
||||
|
||||
@lisp
|
||||
(use-package edit-server
|
||||
:if window-system
|
||||
:init
|
||||
(add-hook 'after-init-hook 'server-start t)
|
||||
(add-hook 'after-init-hook 'edit-server-start t))
|
||||
@end lisp
|
||||
|
||||
In another example, we can load things conditional on the operating system:
|
||||
|
||||
@lisp
|
||||
(use-package exec-path-from-shell
|
||||
:if (memq window-system '(mac ns))
|
||||
:ensure t
|
||||
:config
|
||||
(exec-path-from-shell-initialize))
|
||||
@end lisp
|
||||
|
||||
Note that @code{:when} is provided as an alias for @code{:if}, and @code{:unless foo} means
|
||||
the same thing as @code{:if (not foo)}.
|
||||
|
||||
@node @code{load-path}
|
||||
@section @code{:load-path}
|
||||
|
||||
If your package needs a directory added to the @code{load-path} in order to load,
|
||||
use @code{:load-path}. This takes a symbol, a function, a string or a list of
|
||||
strings. If the path is relative, it is expanded within
|
||||
@code{user-emacs-directory}:
|
||||
|
||||
@lisp
|
||||
(use-package ess-site
|
||||
:load-path "site-lisp/ess/lisp/"
|
||||
:commands R)
|
||||
@end lisp
|
||||
|
||||
Note that when using a symbol or a function to provide a dynamically generated
|
||||
list of paths, you must inform the byte-compiler of this definition so the
|
||||
value is available at byte-compilation time. This is done by using the special
|
||||
form @code{eval-and-compile} (as opposed to @code{eval-when-compile}). Further, this
|
||||
value is fixed at whatever was determined during compilation, to avoid looking
|
||||
up the same information again on each startup:
|
||||
|
||||
@lisp
|
||||
(eval-and-compile
|
||||
(defun ess-site-load-path ()
|
||||
(shell-command "find ~ -path ess/lisp")))
|
||||
|
||||
(use-package ess-site
|
||||
:load-path (lambda () (list (ess-site-load-path)))
|
||||
:commands R)
|
||||
@end lisp
|
||||
|
||||
@node @code{mode} @code{interpreter}
|
||||
@section @code{:mode}, @code{:interpreter}
|
||||
|
||||
Similar to @code{:bind}, you can use @code{:mode} and @code{:interpreter} to establish a
|
||||
deferred binding within the @code{auto-mode-alist} and @code{interpreter-mode-alist}
|
||||
variables. The specifier to either keyword can be a cons cell, a list of cons
|
||||
cells, or a string or regexp:
|
||||
|
||||
@lisp
|
||||
(use-package ruby-mode
|
||||
:mode "\\.rb\\'"
|
||||
:interpreter "ruby")
|
||||
|
||||
;; The package is "python" but the mode is "python-mode":
|
||||
(use-package python
|
||||
:mode ("\\.py\\'" . python-mode)
|
||||
:interpreter ("python" . python-mode))
|
||||
@end lisp
|
||||
|
||||
If you aren't using @code{:commands}, @code{:bind}, @code{:bind*}, @code{:bind-keymap},
|
||||
@code{:bind-keymap*}, @code{:mode}, or @code{:interpreter} (all of which imply @code{:defer}; see
|
||||
the docstring for @code{use-package} for a brief description of each), you can
|
||||
still defer loading with the @code{:defer} keyword:
|
||||
|
||||
@lisp
|
||||
(use-package ace-jump-mode
|
||||
:defer t
|
||||
:init
|
||||
(autoload 'ace-jump-mode "ace-jump-mode" nil t)
|
||||
(bind-key "C-." 'ace-jump-mode))
|
||||
@end lisp
|
||||
|
||||
This does exactly the same thing as the following:
|
||||
|
||||
@lisp
|
||||
(use-package ace-jump-mode
|
||||
:bind ("C-." . ace-jump-mode))
|
||||
@end lisp
|
||||
|
||||
@node @code{magic} @code{magic-fallback}
|
||||
@section @code{:magic}, @code{:magic-fallback}
|
||||
|
||||
Similar to @code{:mode} and @code{:interpreter}, you can also use @code{:magic} and
|
||||
@code{:magic-fallback} to cause certain function to be run if the beginning of a
|
||||
file matches a given regular expression. The difference between the two is
|
||||
that @code{:magic-fallback} has a lower priority than @code{:mode}. For example:
|
||||
|
||||
@lisp
|
||||
(use-package pdf-tools
|
||||
:load-path "site-lisp/pdf-tools/lisp"
|
||||
:magic ("%PDF" . pdf-view-mode)
|
||||
:config
|
||||
(pdf-tools-install))
|
||||
@end lisp
|
||||
|
||||
This registers an autoloaded command for @code{pdf-view-mode}, defers loading of
|
||||
@code{pdf-tools}, and runs @code{pdf-view-mode} if the beginning of a buffer matches the
|
||||
string @code{"%PDF"}.
|
||||
|
||||
@node @code{no-require}
|
||||
@section @code{:no-require}
|
||||
|
||||
Normally, @code{use-package} will load each package at compile time before
|
||||
compiling the configuration, to ensure that any necessary symbols are in scope
|
||||
to satisfy the byte-compiler. At times this can cause problems, since a
|
||||
package may have special loading requirements, and all that you want to use
|
||||
@code{use-package} for is to add a configuration to the @code{eval-after-load} hook. In
|
||||
such cases, use the @code{:no-require} keyword:
|
||||
|
||||
@lisp
|
||||
(use-package foo
|
||||
:no-require t
|
||||
:config
|
||||
(message "This is evaluated when `foo' is loaded"))
|
||||
@end lisp
|
||||
|
||||
@node @code{requires}
|
||||
@section @code{:requires}
|
||||
|
||||
While the @code{:after} keyword delays loading until the dependencies are loaded,
|
||||
the somewhat simpler @code{:requires} keyword simply never loads the package if the
|
||||
dependencies are not available at the time the @code{use-package} declaration is
|
||||
encountered. By "available" in this context it means that @code{foo} is available
|
||||
of @code{(featurep 'foo)} evaluates to a non-nil value. For example:
|
||||
|
||||
@lisp
|
||||
(use-package abbrev
|
||||
:requires foo)
|
||||
@end lisp
|
||||
|
||||
This is the same as:
|
||||
|
||||
@lisp
|
||||
(use-package abbrev
|
||||
:if (featurep 'foo))
|
||||
@end lisp
|
||||
|
||||
As a convenience, a list of such packages may be specified:
|
||||
|
||||
@lisp
|
||||
(use-package abbrev
|
||||
:requires (foo bar baz))
|
||||
@end lisp
|
||||
|
||||
For more complex logic, such as that supported by @code{:after}, simply use @code{:if}
|
||||
and the appropriate Lisp expression.
|
||||
|
||||
@node Debugging Tools
|
||||
@chapter Debugging Tools
|
||||
|
||||
TODO
|
||||
|
||||
@bye
|
||||
277
etc/USE-PACKAGE-NEWS
Normal file
277
etc/USE-PACKAGE-NEWS
Normal file
|
|
@ -0,0 +1,277 @@
|
|||
# Changes
|
||||
|
||||
## 2.4.4
|
||||
|
||||
This release prepares for inclusion to GNU ELPA and includes no other changes
|
||||
|
||||
## 2.4.1
|
||||
|
||||
This is mostly a bug-fix release:
|
||||
|
||||
- Update the documentation for :custom as per #850
|
||||
|
||||
- Fix broken test due to #850
|
||||
|
||||
- better tests
|
||||
|
||||
- add test for #845
|
||||
|
||||
- Support keymap symbol in bind-key. Fix #845
|
||||
|
||||
- use-package-core.el: use the Emacs set-default function to avoid saving :custom vars twice
|
||||
|
||||
- Fix Travis
|
||||
|
||||
- typo, should be a vector, not a bytecode object
|
||||
|
||||
Solves https://github.com/jwiegley/use-package/issues/842
|
||||
|
||||
- Add special value back again, in case needed for backwards compat
|
||||
|
||||
I don't know why this special value exists, but perhaps old client code uses it.
|
||||
|
||||
The additional `t' in the macro expansion is accidental but not harmful I guess.
|
||||
|
||||
- Even when there's no :config, run any pre/post config hooks
|
||||
|
||||
i.e., following the existing docs for use-package-inject-hooks, these hooks are
|
||||
run:
|
||||
|
||||
use-package--foo--pre-config-hook
|
||||
use-package--foo--post-config-hook
|
||||
|
||||
This should make config customisations more predictable (for example, spacemacs
|
||||
uses these hooks extensively to allow 'layers' to be customised).
|
||||
|
||||
I got rid of the "special" default value for :config, because it doesn't seem to
|
||||
be treated any differently than nil.
|
||||
|
||||
Fixes #785
|
||||
|
||||
- Clarify the documentation for :after
|
||||
|
||||
- add table of contents to README
|
||||
|
||||
- Fix typos
|
||||
|
||||
Typos found with codespell.
|
||||
|
||||
- Fix typos
|
||||
|
||||
- Attempt to explain omit "-hook" better
|
||||
|
||||
- Update tests
|
||||
|
||||
- Switch from `require' to `load' + `featurep'
|
||||
|
||||
- Use `require', not `load', when byte-compiling
|
||||
|
||||
- Make custom-face evaluate elisp.
|
||||
|
||||
Fix #696.
|
||||
|
||||
- Add a line of documentation for (use-pacakage ... :hook).
|
||||
|
||||
- Fix typo in README
|
||||
|
||||
- Fix documentation for defer
|
||||
|
||||
- Add no-query option for pdf-tools-install
|
||||
|
||||
- Fix typo in README
|
||||
|
||||
- Fix all notes in README
|
||||
|
||||
- Mention use-package-ensure in README
|
||||
|
||||
Without requiring `use-package-ensure`, setting `use-package-always-ensure`
|
||||
did not actually work for me.
|
||||
|
||||
## 2.4
|
||||
|
||||
### Breaking changes
|
||||
|
||||
- `use-package` no longer requires `diminish` as a dependency, allowing people
|
||||
to decide whether they want to use diminish or delight. This means that if
|
||||
you do use diminish, you'll now need to pull it into your configuration
|
||||
before any use of the `:diminish` kewyord. For example:
|
||||
|
||||
``` elisp
|
||||
(use-package diminish :ensure t)
|
||||
```
|
||||
|
||||
- Emacs 24.3 or higher is now a requirement.
|
||||
|
||||
- The `:defer-install` keyword has been removed. It may reappear as an add-on
|
||||
module for use-package in a future release. See issue #442 for more details.
|
||||
|
||||
- There is no longer a `use-package-debug` option, since `use-package-verbose`
|
||||
already has the possible value of `debug`.
|
||||
|
||||
- The ordering of several elements of `use-package-keywords` have changed; if
|
||||
you had previously customized this (or were an extension author adding to
|
||||
this list), you may need to rework your changes.
|
||||
|
||||
- For extension authors, `:commands` should no longer be propagated down for
|
||||
autoloading. See more below.
|
||||
|
||||
### Other changes
|
||||
|
||||
- Upgrade license to GPL 3.
|
||||
|
||||
- If `use-package-verbose` is set to the symbol `debug`, any evaluation errors
|
||||
during package configuration will cause a complete report to be written to a
|
||||
`*use-package*` buffer, including: the text of the error, the `use-package`
|
||||
declaration that caused the error, the post-normalized form of this
|
||||
declaration, and the macro-expanded version (without verbosity-related
|
||||
code). Note that this still does not help if there are parsing errors, which
|
||||
cause Emacs to register a Lisp error at startup time.
|
||||
|
||||
- New customization variable `use-package-deferring-keywords`, mainly intended
|
||||
for use by extension packages, indicates keywords that, if used without
|
||||
`:demand`, cause deferred loading (as if `:defer t` had been specified).
|
||||
|
||||
- The `:ensure` keyword now accepts a specific pinning sub-keyword. For
|
||||
example:
|
||||
|
||||
``` elisp
|
||||
(use-package foo
|
||||
:pin "elpa")
|
||||
```
|
||||
|
||||
This ensure the package `foo` is installed from `"elpa"`.
|
||||
|
||||
``` elisp
|
||||
(use-package foo
|
||||
:ensure bar
|
||||
:ensure (quux :pin "melpa"))
|
||||
```
|
||||
|
||||
This says that `foo` ensures that `bar` is installed, as well as `quux` from
|
||||
`"melpa"`. It does *not* ensure that `foo` is installed, because explicit
|
||||
`:ensure` keywords were given.
|
||||
|
||||
- New `:hook` keyword.
|
||||
|
||||
- New `:catch` keyword. If `t` or `nil`, it enables (the default, see
|
||||
`use-package-defaults`) or disables catching errors at load time in
|
||||
use-package expansions. It can also be a function taking two arguments: the
|
||||
keyword being processed at the time the error was encountered, and the error
|
||||
object (as generated by `condition-case`).
|
||||
|
||||
- New keywords `:custom (foo1 bar1) (foo2 bar2)` etc., and `:custom-face`.
|
||||
|
||||
NOTE: These are only for people who wish to keep customizations with their
|
||||
accompanying use-package declarations. Functionally, the only benefit over
|
||||
using `setq` in a `:config` block is that customizations might execute code
|
||||
when values are assigned. If you currently use `M-x customize-option` and
|
||||
save to a settings file, you do not want to use this option.
|
||||
|
||||
- New `:magic` and `:magic-fallback` keywords.
|
||||
|
||||
- New `:defer-install` keyword.
|
||||
|
||||
- New customization variable `use-package-enable-imenu-support`.
|
||||
|
||||
- New customization variable `use-package-hook-name-suffix`. Any symbols named
|
||||
in `:hook`, or in the CAR of cons cells passed to `:hook`, have this text
|
||||
appended to them as a convenience. If you find yourself using this keyword
|
||||
to add to hooks of different names, or just don't want such appending done,
|
||||
you can change the text to an empty string.
|
||||
|
||||
- New customization variable `use-package-compute-statistics`, and an
|
||||
accompanying command `M-x use-package-report`. See the README for more
|
||||
details.
|
||||
|
||||
- Allow `:diminish` to take no arguments.
|
||||
|
||||
- Support multiple symbols passed to `:after`, and a mini-DSL using `:all` and
|
||||
`:any`.
|
||||
|
||||
- `:mode` and `:interpreter` can now accept `(rx ...)` forms.
|
||||
|
||||
- Using `:load-path` without also using `:ensure` now implies `:ensure nil`.
|
||||
|
||||
- `:bind (:map foo-map ...)` now defers binding in the map until the package
|
||||
has been loaded.
|
||||
|
||||
- Print key bindings for keymaps in `describe-personal-keybindings`.
|
||||
|
||||
- When `use-package-inject-hooks` is non-nil, always fire `:init` and
|
||||
`:config` hooks.
|
||||
|
||||
- Documentation added for the `:after`, `:defer-install`, `:delight`,
|
||||
`:requires`, `:when` and `:unless` keywords.
|
||||
|
||||
- `:requires SYM` is subtly different from `:if (featurep SYM)`, in that it
|
||||
happens before the `:preface`. This means that using `:requires` will cause
|
||||
definitions in the `:preface` to not be visible to the byte-compiler,
|
||||
leading to possible warnings about unknown functions, or functions that may
|
||||
not be available at run-time (which can generally be ignored, since
|
||||
`:requires` is intended as a check for basic system functionality; `:after`
|
||||
should be used to check for the presence of other modules).
|
||||
|
||||
- New undocumented (and currently experimental) keyword `:load` may be used to
|
||||
change the name of the actual package loaded, rather than the package name,
|
||||
and may even add other names. For example: `(use-package auctex :load
|
||||
tex-site)`. This keyword is used internally to generate the `require` for a
|
||||
package, so that deferral is simply a matter of not generating this keyword.
|
||||
|
||||
- The source code is now broken into several files, so that certain optional
|
||||
features (diminish, delight, ensure) may be maintained separately from the
|
||||
core functionality.
|
||||
|
||||
- When using the `:after` keyword, now even autoloadeds keybinding are
|
||||
deferred until after that other package has loaded, in order to allow
|
||||
convenient `:bind` to maps only present in that other package. Consider the
|
||||
following:
|
||||
|
||||
``` elisp
|
||||
(use-package helm-descbinds
|
||||
:load-path "site-lisp/helm-descbinds"
|
||||
:after helm
|
||||
:bind ("C-h b" . helm-descbinds)
|
||||
:init
|
||||
(fset 'describe-bindings 'helm-descbinds))
|
||||
```
|
||||
|
||||
The binding of `C-h b` here will not occur until helm is loaded; and after
|
||||
it is loaded, `helm-descbinds` itself is not loaded until the user presses
|
||||
`C-h b`.
|
||||
|
||||
- For extension authors, if you add a keyword to `use-package-keywords` whose
|
||||
presence should indicate deferred loading, please also add it to
|
||||
`use-package-deferring-keywords`. Note that this is a bit of a sledgehammer,
|
||||
in that the mere presence of these keywords implies deferred loading. For a
|
||||
more subtle approach, see the new `use-package-autoloads/<KEYWORD>` support
|
||||
mentioned in the next bullet.
|
||||
|
||||
- For extension authors, if you wish deferred loading to possibly occur,
|
||||
create functions named `use-package-autoloads/<KEYWORD>` for each keyword
|
||||
that you define, returning an alist of the form `(SYMBOL . TYPE)` of symbols
|
||||
to be autoloaded. `SYMBOL` should be an interactive function, and `TYPE` the
|
||||
smybol `command`, but this functionality may be extended in future. These
|
||||
autoloads are established if deferred loading is to happen.
|
||||
|
||||
- If you specify a lambda form rather than a function symbol in any of the
|
||||
constructs that *might* introduce autoloads: `:bind`, `:bind*`,
|
||||
`:interpreter`, `:mode`, `:magic`, `:magic-fallback`, and `:hook`: then
|
||||
deferred loading will no longer be implied, since there's nothing to
|
||||
associate an autoload with that could later load the module. In these cases,
|
||||
it will be as if you'd specified `:demand t`, in order to ensure the lambda
|
||||
form is able to execute in the context of the loaded package.
|
||||
|
||||
- For extension authors, there is a new customization variable
|
||||
`use-package-merge-key-alist` that specifies how values passed to multiple
|
||||
occurrences of the same key should be merged into a single value, during
|
||||
normalization of the `use-package` declaration into a proper plist. The
|
||||
default behavior is to simply append the values together (since they are
|
||||
always normalized to lists).
|
||||
|
||||
### Bug fixes
|
||||
|
||||
- Repeating a bind no longer causes duplicates in personal-keybindings.
|
||||
- When byte-compiling, correctly output declare-function directives.
|
||||
- Append to *use-package* when debugging, don't clear it.
|
||||
- Don't allow :commands, :bind, etc., to be given an empty list.
|
||||
- Explicit :defer t should override use-package-always-demand.
|
||||
113
lisp/use-package/bind-chord.el
Normal file
113
lisp/use-package/bind-chord.el
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
;;; bind-chord.el --- key-chord binding helper for use-package-chords -*- lexical-binding: t; -*-
|
||||
|
||||
;; Copyright (C) 2015-2022 Free Software Foundation, Inc.
|
||||
|
||||
;; Author: Justin Talbott <justin@waymondo.com>
|
||||
;; Keywords: convenience, tools, extensions
|
||||
;; URL: https://github.com/jwiegley/use-package
|
||||
;; Version: 0.2.1
|
||||
;; Package-Requires: ((emacs "24.3") (bind-key "1.0") (key-chord "0.6"))
|
||||
;; Filename: bind-chord.el
|
||||
|
||||
;; 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 3 of the License, 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 this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Commentary:
|
||||
|
||||
;;; Code:
|
||||
|
||||
(require 'bind-key)
|
||||
(require 'key-chord nil t)
|
||||
|
||||
;;;###autoload
|
||||
(defmacro bind-chord (chord command &optional keymap)
|
||||
"Bind CHORD to COMMAND in KEYMAP (`global-map' if not passed)."
|
||||
(let ((key1 (logand 255 (aref chord 0)))
|
||||
(key2 (logand 255 (aref chord 1))))
|
||||
(if (eq key1 key2)
|
||||
`(bind-key (vector 'key-chord ,key1 ,key2) ,command ,keymap)
|
||||
`(progn
|
||||
(bind-key (vector 'key-chord ,key1 ,key2) ,command ,keymap)
|
||||
(bind-key (vector 'key-chord ,key2 ,key1) ,command ,keymap)))))
|
||||
|
||||
(defun bind-chords-form (args keymap)
|
||||
"Bind multiple chords at once.
|
||||
|
||||
Accepts keyword arguments:
|
||||
:map MAP - a keymap into which the keybindings should be
|
||||
added
|
||||
|
||||
The rest of the arguments are conses of keybinding string and a
|
||||
function symbol (unquoted)."
|
||||
(let (map pkg)
|
||||
(let ((cont t))
|
||||
(while (and cont args)
|
||||
(if (cond ((eq :map (car args))
|
||||
(setq map (cadr args)))
|
||||
((eq :package (car args))
|
||||
(setq pkg (cadr args))))
|
||||
(setq args (cddr args))
|
||||
(setq cont nil))))
|
||||
|
||||
(unless map (setq map keymap))
|
||||
|
||||
(let (first next)
|
||||
(while args
|
||||
(if (keywordp (car args))
|
||||
(progn
|
||||
(setq next args)
|
||||
(setq args nil))
|
||||
(if first
|
||||
(nconc first (list (car args)))
|
||||
(setq first (list (car args))))
|
||||
(setq args (cdr args))))
|
||||
|
||||
(cl-flet
|
||||
((wrap (map bindings)
|
||||
(if (and map pkg (not (memq map '(global-map
|
||||
override-global-map))))
|
||||
`((if (boundp ',map)
|
||||
,(macroexp-progn bindings)
|
||||
(eval-after-load
|
||||
,(if (symbolp pkg) `',pkg pkg)
|
||||
',(macroexp-progn bindings))))
|
||||
bindings)))
|
||||
|
||||
(append
|
||||
(wrap map
|
||||
(cl-mapcan
|
||||
(lambda (form)
|
||||
(let ((fun (and (cdr form) (list 'function (cdr form)))))
|
||||
(if (and map (not (eq map 'global-map)))
|
||||
`((bind-chord ,(car form) ,fun ,map))
|
||||
`((bind-chord ,(car form) ,fun nil)))))
|
||||
first))
|
||||
(when next
|
||||
(bind-chords-form (if pkg
|
||||
(cons :package (cons pkg next))
|
||||
next) map)))))))
|
||||
|
||||
;;;###autoload
|
||||
(defmacro bind-chords (&rest args)
|
||||
"Bind multiple chords at once.
|
||||
|
||||
Accepts keyword argument:
|
||||
:map - a keymap into which the keybindings should be added
|
||||
|
||||
The rest of the arguments are conses of keybinding string and a
|
||||
function symbol (unquoted)."
|
||||
(macroexp-progn (bind-chords-form args nil)))
|
||||
|
||||
(provide 'bind-chord)
|
||||
|
||||
;;; bind-chord.el ends here
|
||||
544
lisp/use-package/bind-key.el
Normal file
544
lisp/use-package/bind-key.el
Normal file
|
|
@ -0,0 +1,544 @@
|
|||
;;; bind-key.el --- A simple way to manage personal keybindings -*- lexical-binding: t; -*-
|
||||
|
||||
;; Copyright (c) 2012-2022 Free Software Foundation, Inc.
|
||||
|
||||
;; Author: John Wiegley <johnw@newartisans.com>
|
||||
;; Maintainer: John Wiegley <johnw@newartisans.com>
|
||||
;; Created: 16 Jun 2012
|
||||
;; Version: 2.4.1
|
||||
;; Package-Requires: ((emacs "24.3"))
|
||||
;; Keywords: keys keybinding config dotemacs extensions
|
||||
;; 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 3 of the License, 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 this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
;;; 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 the keybinding argument is a vector, it is passed straight to
|
||||
;; `define-key', so remapping a key with `[remap COMMAND]' works as
|
||||
;; expected:
|
||||
;;
|
||||
;; (bind-key [remap original-ctrl-c-x-command] '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 keymap, 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)
|
||||
;;
|
||||
;; To bind multiple keys at once, or set up a prefix map, a `bind-keys' macro
|
||||
;; is provided. It accepts keyword arguments, please see its documentation
|
||||
;; for a 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:
|
||||
;;
|
||||
;; M-x describe-personal-keybindings
|
||||
;;
|
||||
;; This display will tell you if you've overridden 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.
|
||||
|
||||
;;; Code:
|
||||
|
||||
(require 'cl-lib)
|
||||
(require 'easy-mmode)
|
||||
|
||||
(defgroup bind-key nil
|
||||
"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
|
||||
\\[describe-personal-keybindings]."
|
||||
: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)
|
||||
"Keymap for `override-global-mode'.")
|
||||
|
||||
(define-minor-mode override-global-mode
|
||||
"A minor mode so that keymap settings override other modes."
|
||||
:init-value t
|
||||
:lighter "")
|
||||
|
||||
;; the keymaps in `emulation-mode-map-alists' take precedence over
|
||||
;; `minor-mode-map-alist'
|
||||
(add-to-list 'emulation-mode-map-alists
|
||||
`((override-global-mode . ,override-global-map)))
|
||||
|
||||
(defvar personal-keybindings nil
|
||||
"List of bindings performed by `bind-key'.
|
||||
|
||||
Elements have the form ((KEY . [MAP]) CMD ORIGINAL-CMD)")
|
||||
|
||||
;;;###autoload
|
||||
(defmacro bind-key (key-name command &optional keymap predicate)
|
||||
"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.
|
||||
|
||||
COMMAND must be an interactive function or lambda form.
|
||||
|
||||
KEYMAP, if present, should be a keymap variable or symbol.
|
||||
For example:
|
||||
|
||||
(bind-key \"M-h\" #\\='some-interactive-function my-mode-map)
|
||||
|
||||
(bind-key \"M-h\" #\\='some-interactive-function \\='my-mode-map)
|
||||
|
||||
If PREDICATE is non-nil, it is a form evaluated to determine when
|
||||
a key should be bound. It must return non-nil in such cases.
|
||||
Emacs can evaluate this form at any time that it does redisplay
|
||||
or operates on menu data structures, so you should write it so it
|
||||
can safely be called at any time."
|
||||
(let ((namevar (make-symbol "name"))
|
||||
(keyvar (make-symbol "key"))
|
||||
(kmapvar (make-symbol "kmap"))
|
||||
(kdescvar (make-symbol "kdesc"))
|
||||
(bindingvar (make-symbol "binding")))
|
||||
`(let* ((,namevar ,key-name)
|
||||
(,keyvar ,(if (stringp key-name) (read-kbd-macro key-name)
|
||||
`(if (vectorp ,namevar) ,namevar
|
||||
(read-kbd-macro ,namevar))))
|
||||
(,kmapvar (or (if (and ,keymap (symbolp ,keymap))
|
||||
(symbol-value ,keymap) ,keymap)
|
||||
global-map))
|
||||
(,kdescvar (cons (if (stringp ,namevar) ,namevar
|
||||
(key-description ,namevar))
|
||||
(if (symbolp ,keymap) ,keymap (quote ,keymap))))
|
||||
(,bindingvar (lookup-key ,kmapvar ,keyvar)))
|
||||
(let ((entry (assoc ,kdescvar personal-keybindings))
|
||||
(details (list ,command
|
||||
(unless (numberp ,bindingvar)
|
||||
,bindingvar))))
|
||||
(if entry
|
||||
(setcdr entry details)
|
||||
(add-to-list 'personal-keybindings (cons ,kdescvar details))))
|
||||
,(if predicate
|
||||
`(define-key ,kmapvar ,keyvar
|
||||
'(menu-item "" nil :filter (lambda (&optional _)
|
||||
(when ,predicate
|
||||
,command))))
|
||||
`(define-key ,kmapvar ,keyvar ,command)))))
|
||||
|
||||
;;;###autoload
|
||||
(defmacro unbind-key (key-name &optional keymap)
|
||||
"Unbind the given KEY-NAME, within the KEYMAP (if specified).
|
||||
See `bind-key' for more details."
|
||||
(let ((namevar (make-symbol "name"))
|
||||
(kdescvar (make-symbol "kdesc")))
|
||||
`(let* ((,namevar ,key-name)
|
||||
(,kdescvar (cons (if (stringp ,namevar) ,namevar
|
||||
(key-description ,namevar))
|
||||
(if (symbolp ,keymap) ,keymap (quote ,keymap)))))
|
||||
(bind-key--remove (if (vectorp ,namevar) ,namevar
|
||||
(read-kbd-macro ,namevar))
|
||||
(or (if (and ,keymap (symbolp ,keymap))
|
||||
(symbol-value ,keymap) ,keymap)
|
||||
global-map))
|
||||
(setq personal-keybindings
|
||||
(cl-delete-if (lambda (k) (equal (car k) ,kdescvar))
|
||||
personal-keybindings))
|
||||
nil)))
|
||||
|
||||
(defun bind-key--remove (key keymap)
|
||||
"Remove KEY from KEYMAP.
|
||||
|
||||
In contrast to `define-key', this function removes the binding from the keymap."
|
||||
(define-key keymap key nil)
|
||||
;; Split M-key in ESC key
|
||||
(setq key (cl-mapcan (lambda (k)
|
||||
(if (and (integerp k) (/= (logand k ?\M-\0) 0))
|
||||
(list ?\e (logxor k ?\M-\0))
|
||||
(list k)))
|
||||
key))
|
||||
;; Delete single keys directly
|
||||
(if (= (length key) 1)
|
||||
(delete key keymap)
|
||||
;; Lookup submap and delete key from there
|
||||
(let* ((prefix (vconcat (butlast key)))
|
||||
(submap (lookup-key keymap prefix)))
|
||||
(unless (keymapp submap)
|
||||
(error "Not a keymap for %s" key))
|
||||
(when (symbolp submap)
|
||||
(setq submap (symbol-function submap)))
|
||||
(delete (last key) submap)
|
||||
;; Delete submap if it is empty
|
||||
(when (= 1 (length submap))
|
||||
(bind-key--remove prefix keymap)))))
|
||||
|
||||
;;;###autoload
|
||||
(defmacro bind-key* (key-name command &optional predicate)
|
||||
"Similar to `bind-key', but overrides any mode-specific bindings."
|
||||
`(bind-key ,key-name ,command override-global-map ,predicate))
|
||||
|
||||
(defun bind-keys-form (args keymap)
|
||||
"Bind multiple keys at once.
|
||||
|
||||
Accepts keyword arguments:
|
||||
:map MAP - a keymap into which the keybindings should be
|
||||
added
|
||||
:prefix KEY - prefix key for these bindings
|
||||
:prefix-map MAP - name of the prefix map that should be created
|
||||
for these bindings
|
||||
:prefix-docstring STR - docstring for the prefix-map variable
|
||||
:menu-name NAME - optional menu string for prefix map
|
||||
:repeat-docstring STR - docstring for the repeat-map variable
|
||||
:repeat-map MAP - name of the repeat map that should be created
|
||||
for these bindings. If specified, the
|
||||
`repeat-map' property of each command bound
|
||||
(within the scope of the `:repeat-map' keyword)
|
||||
is set to this map.
|
||||
:exit BINDINGS - Within the scope of `:repeat-map' will bind the
|
||||
key in the repeat map, but will not set the
|
||||
`repeat-map' property of the bound command.
|
||||
:continue BINDINGS - Within the scope of `:repeat-map' forces the
|
||||
same behaviour as if no special keyword had
|
||||
been used (that is, the command is bound, and
|
||||
it's `repeat-map' property set)
|
||||
:filter FORM - optional form to determine when bindings apply
|
||||
|
||||
The rest of the arguments are conses of keybinding string and a
|
||||
function symbol (unquoted)."
|
||||
(let (map
|
||||
prefix-doc
|
||||
prefix-map
|
||||
prefix
|
||||
repeat-map
|
||||
repeat-doc
|
||||
repeat-type ;; Only used internally
|
||||
filter
|
||||
menu-name
|
||||
pkg)
|
||||
|
||||
;; Process any initial keyword arguments
|
||||
(let ((cont t)
|
||||
(arg-change-func 'cddr))
|
||||
(while (and cont args)
|
||||
(if (cond ((and (eq :map (car args))
|
||||
(not prefix-map))
|
||||
(setq map (cadr args)))
|
||||
((eq :prefix-docstring (car args))
|
||||
(setq prefix-doc (cadr args)))
|
||||
((and (eq :prefix-map (car args))
|
||||
(not (memq map '(global-map
|
||||
override-global-map))))
|
||||
(setq prefix-map (cadr args)))
|
||||
((eq :repeat-docstring (car args))
|
||||
(setq repeat-doc (cadr args)))
|
||||
((and (eq :repeat-map (car args))
|
||||
(not (memq map '(global-map
|
||||
override-global-map))))
|
||||
(setq repeat-map (cadr args))
|
||||
(setq map repeat-map))
|
||||
((eq :continue (car args))
|
||||
(setq repeat-type :continue
|
||||
arg-change-func 'cdr))
|
||||
((eq :exit (car args))
|
||||
(setq repeat-type :exit
|
||||
arg-change-func 'cdr))
|
||||
((eq :prefix (car args))
|
||||
(setq prefix (cadr args)))
|
||||
((eq :filter (car args))
|
||||
(setq filter (cadr args)) t)
|
||||
((eq :menu-name (car args))
|
||||
(setq menu-name (cadr args)))
|
||||
((eq :package (car args))
|
||||
(setq pkg (cadr args))))
|
||||
(setq args (funcall arg-change-func args))
|
||||
(setq cont nil))))
|
||||
|
||||
(when (or (and prefix-map (not prefix))
|
||||
(and prefix (not prefix-map)))
|
||||
(error "Both :prefix-map and :prefix must be supplied"))
|
||||
|
||||
(when repeat-type
|
||||
(unless repeat-map
|
||||
(error ":continue and :exit require specifying :repeat-map")))
|
||||
|
||||
(when (and menu-name (not prefix))
|
||||
(error "If :menu-name is supplied, :prefix must be too"))
|
||||
|
||||
(unless map (setq map keymap))
|
||||
|
||||
;; Process key binding arguments
|
||||
(let (first next)
|
||||
(while args
|
||||
(if (keywordp (car args))
|
||||
(progn
|
||||
(setq next args)
|
||||
(setq args nil))
|
||||
(if first
|
||||
(nconc first (list (car args)))
|
||||
(setq first (list (car args))))
|
||||
(setq args (cdr args))))
|
||||
|
||||
(cl-flet
|
||||
((wrap (map bindings)
|
||||
(if (and map pkg (not (memq map '(global-map
|
||||
override-global-map))))
|
||||
`((if (boundp ',map)
|
||||
,(macroexp-progn bindings)
|
||||
(eval-after-load
|
||||
,(if (symbolp pkg) `',pkg pkg)
|
||||
',(macroexp-progn bindings))))
|
||||
bindings)))
|
||||
|
||||
(append
|
||||
(when prefix-map
|
||||
`((defvar ,prefix-map)
|
||||
,@(when prefix-doc `((put ',prefix-map 'variable-documentation ,prefix-doc)))
|
||||
,@(if menu-name
|
||||
`((define-prefix-command ',prefix-map nil ,menu-name))
|
||||
`((define-prefix-command ',prefix-map)))
|
||||
,@(if (and map (not (eq map 'global-map)))
|
||||
(wrap map `((bind-key ,prefix ',prefix-map ,map ,filter)))
|
||||
`((bind-key ,prefix ',prefix-map nil ,filter)))))
|
||||
(when repeat-map
|
||||
`((defvar ,repeat-map (make-sparse-keymap)
|
||||
,@(when repeat-doc `(,repeat-doc)))))
|
||||
(wrap map
|
||||
(cl-mapcan
|
||||
(lambda (form)
|
||||
(let ((fun (and (cdr form) (list 'function (cdr form)))))
|
||||
(if prefix-map
|
||||
`((bind-key ,(car form) ,fun ,prefix-map ,filter))
|
||||
(if (and map (not (eq map 'global-map)))
|
||||
;; Only needed in this branch, since when
|
||||
;; repeat-map is non-nil, map is always
|
||||
;; non-nil
|
||||
`(,@(when (and repeat-map (not (eq repeat-type :exit)))
|
||||
`((put ,fun 'repeat-map ',repeat-map)))
|
||||
(bind-key ,(car form) ,fun ,map ,filter))
|
||||
`((bind-key ,(car form) ,fun nil ,filter))))))
|
||||
first))
|
||||
(when next
|
||||
(bind-keys-form `(,@(when repeat-map `(:repeat-map ,repeat-map))
|
||||
,@(if pkg
|
||||
(cons :package (cons pkg next))
|
||||
next)) map)))))))
|
||||
|
||||
;;;###autoload
|
||||
(defmacro bind-keys (&rest args)
|
||||
"Bind multiple keys at once.
|
||||
|
||||
Accepts keyword arguments:
|
||||
:map MAP - a keymap into which the keybindings should be
|
||||
added
|
||||
:prefix KEY - prefix key for these bindings
|
||||
:prefix-map MAP - name of the prefix map that should be created
|
||||
for these bindings
|
||||
:prefix-docstring STR - docstring for the prefix-map variable
|
||||
:menu-name NAME - optional menu string for prefix map
|
||||
:repeat-docstring STR - docstring for the repeat-map variable
|
||||
:repeat-map MAP - name of the repeat map that should be created
|
||||
for these bindings. If specified, the
|
||||
`repeat-map' property of each command bound
|
||||
(within the scope of the `:repeat-map' keyword)
|
||||
is set to this map.
|
||||
:exit BINDINGS - Within the scope of `:repeat-map' will bind the
|
||||
key in the repeat map, but will not set the
|
||||
`repeat-map' property of the bound command.
|
||||
:continue BINDINGS - Within the scope of `:repeat-map' forces the
|
||||
same behaviour as if no special keyword had
|
||||
been used (that is, the command is bound, and
|
||||
it's `repeat-map' property set)
|
||||
:filter FORM - optional form to determine when bindings apply
|
||||
|
||||
The rest of the arguments are conses of keybinding string and a
|
||||
function symbol (unquoted)."
|
||||
(macroexp-progn (bind-keys-form args nil)))
|
||||
|
||||
;;;###autoload
|
||||
(defmacro bind-keys* (&rest args)
|
||||
(macroexp-progn (bind-keys-form args 'override-global-map)))
|
||||
|
||||
(defun get-binding-description (elem)
|
||||
(cond
|
||||
((listp elem)
|
||||
(cond
|
||||
((memq (car elem) '(lambda function))
|
||||
(if (and bind-key-describe-special-forms
|
||||
(stringp (nth 2 elem)))
|
||||
(nth 2 elem)
|
||||
"#<lambda>"))
|
||||
((eq 'closure (car elem))
|
||||
(if (and bind-key-describe-special-forms
|
||||
(stringp (nth 3 elem)))
|
||||
(nth 3 elem)
|
||||
"#<closure>"))
|
||||
((eq 'keymap (car elem))
|
||||
"#<keymap>")
|
||||
(t
|
||||
elem)))
|
||||
;; must be a symbol, non-symbol keymap case covered above
|
||||
((and bind-key-describe-special-forms (keymapp elem))
|
||||
(let ((doc (get elem 'variable-documentation)))
|
||||
(if (stringp doc) doc elem)))
|
||||
((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)))))
|
||||
|
||||
;;;###autoload
|
||||
(defun describe-personal-keybindings ()
|
||||
"Display all the personal keybindings defined by `bind-key'."
|
||||
(interactive)
|
||||
(with-output-to-temp-buffer "*Personal Keybindings*"
|
||||
(princ (format (concat "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))))))
|
||||
|
||||
(if (not (eq (cdar last-binding) (cdar binding)))
|
||||
(princ (format "\n\n%s: %s\n%s\n\n"
|
||||
(cdar binding) (caar binding)
|
||||
(make-string (+ 21 (car bind-key-column-widths)
|
||||
(cdr bind-key-column-widths)) ?-)))
|
||||
(if (and last-binding
|
||||
(cdr (compare-keybindings last-binding binding)))
|
||||
(princ "\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)))
|
||||
(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:
|
||||
;; outline-regexp: ";;;\\(;* [^\s\t\n]\\|###autoload\\)\\|("
|
||||
;; End:
|
||||
|
||||
;;; bind-key.el ends here
|
||||
171
lisp/use-package/use-package-bind-key.el
Normal file
171
lisp/use-package/use-package-bind-key.el
Normal file
|
|
@ -0,0 +1,171 @@
|
|||
;;; use-package-bind-key.el --- Support for the :bind/:bind-keymap keywords -*- lexical-binding: t; -*-
|
||||
|
||||
;; Copyright (C) 2012-2022 Free Software Foundation, Inc.
|
||||
|
||||
;; Author: John Wiegley <johnw@newartisans.com>
|
||||
;; Maintainer: John Wiegley <johnw@newartisans.com>
|
||||
|
||||
;; 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 3 of the License, 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 this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Commentary:
|
||||
|
||||
;; Provides support for the :bind, :bind*, :bind-keymap and :bind-keymap*
|
||||
;; keywords. Note that these are currently still baked into
|
||||
;; `use-package-keywords' and `use-package-deferring-keywords', although this
|
||||
;; is harmless if they are never used.
|
||||
|
||||
;;; Code:
|
||||
|
||||
(require 'use-package-core)
|
||||
(require 'bind-key)
|
||||
|
||||
;;;###autoload
|
||||
(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 (not (require package nil t))
|
||||
(use-package-error (format "Cannot load package.el: %s" package))
|
||||
(if (and (boundp keymap-symbol)
|
||||
(keymapp (symbol-value keymap-symbol)))
|
||||
(let* ((kv (this-command-keys-vector))
|
||||
(key (key-description kv))
|
||||
(keymap (symbol-value keymap-symbol)))
|
||||
(if override
|
||||
(bind-key* key keymap)
|
||||
(bind-key key keymap))
|
||||
(setq unread-command-events
|
||||
(mapcar (lambda (ev) (cons t ev))
|
||||
(listify-key-sequence kv))))
|
||||
(use-package-error
|
||||
(format "package.el %s failed to define keymap %s"
|
||||
package keymap-symbol)))))
|
||||
|
||||
;;;###autoload
|
||||
(defun use-package-normalize-binder (name keyword args)
|
||||
(let ((arg args)
|
||||
args*)
|
||||
(while arg
|
||||
(let ((x (car arg)))
|
||||
(cond
|
||||
;; (KEY . COMMAND)
|
||||
((and (consp x)
|
||||
(or (stringp (car x))
|
||||
(vectorp (car x)))
|
||||
(or (use-package-recognize-function (cdr x) t #'stringp)))
|
||||
(setq args* (nconc args* (list x)))
|
||||
(setq arg (cdr arg)))
|
||||
;; KEYWORD
|
||||
;; :map KEYMAP
|
||||
;; :prefix-docstring STRING
|
||||
;; :prefix-map SYMBOL
|
||||
;; :prefix STRING
|
||||
;; :repeat-docstring STRING
|
||||
;; :repeat-map SYMBOL
|
||||
;; :filter SEXP
|
||||
;; :menu-name STRING
|
||||
;; :package SYMBOL
|
||||
;; :continue and :exit are used within :repeat-map
|
||||
((or (and (eq x :map) (symbolp (cadr arg)))
|
||||
(and (eq x :prefix) (stringp (cadr arg)))
|
||||
(and (eq x :prefix-map) (symbolp (cadr arg)))
|
||||
(and (eq x :prefix-docstring) (stringp (cadr arg)))
|
||||
(and (eq x :repeat-map) (symbolp (cadr arg)))
|
||||
(eq x :continue)
|
||||
(eq x :exit)
|
||||
(and (eq x :repeat-docstring) (stringp (cadr arg)))
|
||||
(eq x :filter)
|
||||
(and (eq x :menu-name) (stringp (cadr arg)))
|
||||
(and (eq x :package) (symbolp (cadr arg))))
|
||||
(setq args* (nconc args* (list x (cadr arg))))
|
||||
(setq arg (cddr arg)))
|
||||
((listp x)
|
||||
(setq args*
|
||||
(nconc args* (use-package-normalize-binder name keyword x)))
|
||||
(setq arg (cdr arg)))
|
||||
(t
|
||||
;; Error!
|
||||
(use-package-error
|
||||
(concat (symbol-name name)
|
||||
" wants arguments acceptable to the `bind-keys' macro,"
|
||||
" or a list of such values"))))))
|
||||
args*))
|
||||
|
||||
;;;; :bind, :bind*
|
||||
|
||||
;;;###autoload
|
||||
(defalias 'use-package-normalize/:bind 'use-package-normalize-binder)
|
||||
;;;###autoload
|
||||
(defalias 'use-package-normalize/:bind* 'use-package-normalize-binder)
|
||||
|
||||
;; jww (2017-12-07): This is too simplistic. It will fail to determine
|
||||
;; autoloads in this situation:
|
||||
;; (use-package foo
|
||||
;; :bind (:map foo-map (("C-a" . func))))
|
||||
;;;###autoload
|
||||
(defalias 'use-package-autoloads/:bind 'use-package-autoloads-mode)
|
||||
;;;###autoload
|
||||
(defalias 'use-package-autoloads/:bind* 'use-package-autoloads-mode)
|
||||
|
||||
;;;###autoload
|
||||
(defun use-package-handler/:bind
|
||||
(name _keyword args rest state &optional bind-macro)
|
||||
(use-package-concat
|
||||
(use-package-process-keywords name rest state)
|
||||
`(,@(mapcar
|
||||
#'(lambda (xs)
|
||||
`(,(if bind-macro bind-macro 'bind-keys)
|
||||
:package ,name ,@(use-package-normalize-commands xs)))
|
||||
(use-package-split-list-at-keys :break args)))))
|
||||
|
||||
(defun use-package-handler/:bind* (name keyword arg rest state)
|
||||
(use-package-handler/:bind name keyword arg rest state 'bind-keys*))
|
||||
|
||||
;;;; :bind-keymap, :bind-keymap*
|
||||
|
||||
;;;###autoload
|
||||
(defalias 'use-package-normalize/:bind-keymap 'use-package-normalize-binder)
|
||||
;;;###autoload
|
||||
(defalias 'use-package-normalize/:bind-keymap* 'use-package-normalize-binder)
|
||||
|
||||
;;;###autoload
|
||||
(defun use-package-handler/:bind-keymap
|
||||
(name _keyword args rest state &optional override)
|
||||
(use-package-concat
|
||||
(use-package-process-keywords name rest state)
|
||||
(mapcar
|
||||
#'(lambda (binding)
|
||||
`(,(if override 'bind-key* 'bind-key)
|
||||
,(car binding)
|
||||
#'(lambda ()
|
||||
(interactive)
|
||||
(use-package-autoload-keymap
|
||||
',(cdr binding) ',(use-package-as-symbol name)
|
||||
,override))))
|
||||
args)))
|
||||
|
||||
;;;###autoload
|
||||
(defun use-package-handler/:bind-keymap* (name keyword arg rest state)
|
||||
(use-package-handler/:bind-keymap name keyword arg rest state t))
|
||||
|
||||
(provide 'use-package-bind-key)
|
||||
|
||||
;;; use-package-bind-key.el ends here
|
||||
54
lisp/use-package/use-package-chords.el
Normal file
54
lisp/use-package/use-package-chords.el
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
;;; use-package-chords.el --- key-chord keyword for use-package -*- lexical-binding: t; -*-
|
||||
|
||||
;; Copyright (C) 2015-2022 Free Software Foundation, Inc.
|
||||
|
||||
;; Author: Justin Talbott <justin@waymondo.com>
|
||||
;; Keywords: convenience, tools, extensions
|
||||
;; URL: https://github.com/jwiegley/use-package
|
||||
;; Version: 0.2.1
|
||||
;; Package-Requires: ((use-package "2.1") (bind-key "1.0") (bind-chord "0.2") (key-chord "0.6"))
|
||||
;; Filename: use-package-chords.el
|
||||
|
||||
;; 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 3 of the License, 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 this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Commentary:
|
||||
|
||||
;; The `:chords' keyword allows you to define `key-chord' bindings for
|
||||
;; `use-package' declarations in the same manner as the `:bind'
|
||||
;; keyword.
|
||||
|
||||
;;; Code:
|
||||
|
||||
(require 'use-package)
|
||||
(require 'bind-chord)
|
||||
|
||||
;;;###autoload
|
||||
(defalias 'use-package-autoloads/:chords 'use-package-autoloads-mode)
|
||||
|
||||
;;;###autoload
|
||||
(defalias 'use-package-normalize/:chords 'use-package-normalize-binder)
|
||||
|
||||
;;;###autoload
|
||||
(defun use-package-handler/:chords (name _keyword arg rest state)
|
||||
"Handler for `:chords' keyword in `use-package'."
|
||||
(use-package-concat
|
||||
(use-package-process-keywords name rest state)
|
||||
`(,(macroexpand
|
||||
`(bind-chords :package ,name ,@arg)))))
|
||||
|
||||
(add-to-list 'use-package-keywords :chords)
|
||||
|
||||
(provide 'use-package-chords)
|
||||
|
||||
;;; use-package-chords.el ends here
|
||||
1690
lisp/use-package/use-package-core.el
Normal file
1690
lisp/use-package/use-package-core.el
Normal file
File diff suppressed because it is too large
Load diff
83
lisp/use-package/use-package-delight.el
Normal file
83
lisp/use-package/use-package-delight.el
Normal file
|
|
@ -0,0 +1,83 @@
|
|||
;;; use-package-delight.el --- Support for the :delight keyword -*- lexical-binding: t; -*-
|
||||
|
||||
;; Copyright (C) 2012-2022 Free Software Foundation, Inc.
|
||||
|
||||
;; Author: John Wiegley <johnw@newartisans.com>
|
||||
;; Maintainer: John Wiegley <johnw@newartisans.com>
|
||||
|
||||
;; 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 3 of the License, 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 this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Commentary:
|
||||
|
||||
;; Provides support for the :delight keyword, which is made available by
|
||||
;; default by requiring `use-package'.
|
||||
|
||||
;;; Code:
|
||||
|
||||
(require 'use-package-core)
|
||||
|
||||
(defun use-package-normalize-delight (name args)
|
||||
"Normalize ARGS for a single call to `delight'."
|
||||
(when (eq :eval (car args))
|
||||
;; Handle likely common mistake.
|
||||
(use-package-error ":delight mode line constructs must be quoted"))
|
||||
(cond ((and (= (length args) 1)
|
||||
(use-package-non-nil-symbolp (car args)))
|
||||
`(,(nth 0 args) nil ,name))
|
||||
((= (length args) 2)
|
||||
`(,(nth 0 args) ,(nth 1 args) ,name))
|
||||
((= (length args) 3)
|
||||
args)
|
||||
(t
|
||||
(use-package-error
|
||||
":delight expects `delight' arguments or a list of them"))))
|
||||
|
||||
;;;###autoload
|
||||
(defun use-package-normalize/:delight (name _keyword args)
|
||||
"Normalize arguments to delight."
|
||||
(cond ((null args)
|
||||
`((,(use-package-as-mode name) nil ,name)))
|
||||
((and (= (length args) 1)
|
||||
(use-package-non-nil-symbolp (car args)))
|
||||
`((,(car args) nil ,name)))
|
||||
((and (= (length args) 1)
|
||||
(stringp (car args)))
|
||||
`((,(use-package-as-mode name) ,(car args) ,name)))
|
||||
((and (= (length args) 1)
|
||||
(listp (car args))
|
||||
(eq 'quote (caar args)))
|
||||
`((,(use-package-as-mode name) ,@(cdar args) ,name)))
|
||||
((and (= (length args) 2)
|
||||
(listp (nth 1 args))
|
||||
(eq 'quote (car (nth 1 args))))
|
||||
`((,(car args) ,@(cdr (nth 1 args)) ,name)))
|
||||
(t (mapcar
|
||||
(apply-partially #'use-package-normalize-delight name)
|
||||
(if (use-package-non-nil-symbolp (car args))
|
||||
(list args)
|
||||
args)))))
|
||||
|
||||
;;;###autoload
|
||||
(defun use-package-handler/:delight (name _keyword args rest state)
|
||||
(let ((body (use-package-process-keywords name rest state)))
|
||||
(use-package-concat
|
||||
body
|
||||
`((if (fboundp 'delight)
|
||||
(delight '(,@args)))))))
|
||||
|
||||
(add-to-list 'use-package-keywords :delight t)
|
||||
|
||||
(provide 'use-package-delight)
|
||||
|
||||
;;; use-package-delight.el ends here
|
||||
72
lisp/use-package/use-package-diminish.el
Normal file
72
lisp/use-package/use-package-diminish.el
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
;;; use-package-diminish.el --- Support for the :diminish keyword -*- lexical-binding: t; -*-
|
||||
|
||||
;; Copyright (C) 2012-2022 Free Software Foundation, Inc.
|
||||
|
||||
;; Author: John Wiegley <johnw@newartisans.com>
|
||||
;; Maintainer: John Wiegley <johnw@newartisans.com>
|
||||
|
||||
;; 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 3 of the License, 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 this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Commentary:
|
||||
|
||||
;; Provides support for the :diminish keyword, which is made available by
|
||||
;; default by requiring `use-package'.
|
||||
|
||||
;;; Code:
|
||||
|
||||
(require 'use-package-core)
|
||||
|
||||
(defun use-package-normalize-diminish (name label arg &optional recursed)
|
||||
"Normalize the arguments to diminish down to a list of one of two forms:
|
||||
SYMBOL
|
||||
(SYMBOL . STRING)"
|
||||
(cond
|
||||
((not arg)
|
||||
(list (use-package-as-mode name)))
|
||||
((use-package-non-nil-symbolp arg)
|
||||
(list arg))
|
||||
((stringp arg)
|
||||
(list (cons (use-package-as-mode name) arg)))
|
||||
((and (consp arg) (stringp (cdr arg)))
|
||||
(list arg))
|
||||
((and (not recursed) (listp arg) (listp (cdr arg)))
|
||||
(mapcar #'(lambda (x) (car (use-package-normalize-diminish
|
||||
name label x t))) arg))
|
||||
(t
|
||||
(use-package-error
|
||||
(concat label " wants a string, symbol, "
|
||||
"(symbol . string) or list of these")))))
|
||||
|
||||
;;;###autoload
|
||||
(defun use-package-normalize/:diminish (name keyword args)
|
||||
(use-package-as-one (symbol-name keyword) args
|
||||
(apply-partially #'use-package-normalize-diminish name) t))
|
||||
|
||||
;;;###autoload
|
||||
(defun use-package-handler/:diminish (name _keyword arg rest state)
|
||||
(let ((body (use-package-process-keywords name rest state)))
|
||||
(use-package-concat
|
||||
(mapcar #'(lambda (var)
|
||||
`(if (fboundp 'diminish)
|
||||
,(if (consp var)
|
||||
`(diminish ',(car var) ,(cdr var))
|
||||
`(diminish ',var))))
|
||||
arg)
|
||||
body)))
|
||||
|
||||
(add-to-list 'use-package-keywords :diminish t)
|
||||
|
||||
(provide 'use-package-diminish)
|
||||
|
||||
;;; use-package-diminish.el ends here
|
||||
99
lisp/use-package/use-package-ensure-system-package.el
Normal file
99
lisp/use-package/use-package-ensure-system-package.el
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
;;; use-package-ensure-system-package.el --- auto install system packages -*- lexical-binding: t; -*-
|
||||
|
||||
;; Copyright (C) 2022 Free Software Foundation, Inc.
|
||||
|
||||
;; Author: Justin Talbott <justin@waymondo.com>
|
||||
;; Keywords: convenience, tools, extensions
|
||||
;; URL: https://github.com/waymondo/use-package-ensure-system-package
|
||||
;; Version: 0.2
|
||||
;; Package-Requires: ((use-package "2.1") (system-packages "1.0.4"))
|
||||
;; Filename: use-package-ensure-system-package.el
|
||||
|
||||
;; 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 3 of the License, 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 this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Commentary:
|
||||
;;
|
||||
;; The `:ensure-system-package` keyword allows you to ensure system
|
||||
;; binaries exist alongside your `use-package` declarations.
|
||||
;;
|
||||
|
||||
;;; Code:
|
||||
|
||||
(require 'use-package)
|
||||
(require 'system-packages nil t)
|
||||
|
||||
(eval-when-compile
|
||||
(declare-function system-packages-get-command "system-packages"))
|
||||
|
||||
(defvar use-package-ensure-system-package--custom-packages '()
|
||||
"List of custom packages installed.")
|
||||
|
||||
(defun use-package-ensure-system-package-consify (arg)
|
||||
"Turn ARG into a cons of (`package-name' . `install-command')."
|
||||
(cond
|
||||
((stringp arg)
|
||||
(cons arg `(system-packages-install ,arg)))
|
||||
((symbolp arg)
|
||||
(cons arg `(system-packages-install ,(symbol-name arg))))
|
||||
((consp arg)
|
||||
(cond
|
||||
((not (cdr arg))
|
||||
(use-package-ensure-system-package-consify (car arg)))
|
||||
((stringp (cdr arg))
|
||||
(progn
|
||||
(push (cdr arg) use-package-ensure-system-package--custom-packages)
|
||||
(cons (car arg) `(async-shell-command ,(cdr arg)))))
|
||||
(t
|
||||
(cons (car arg)
|
||||
`(system-packages-install ,(symbol-name (cdr arg)))))))))
|
||||
|
||||
(defun use-package-ensure-system-package-update-custom-packages ()
|
||||
(interactive)
|
||||
(dolist (cmd use-package-ensure-system-package--custom-packages)
|
||||
(async-shell-command cmd)))
|
||||
|
||||
;;;###autoload
|
||||
(defun use-package-normalize/:ensure-system-package (_name-symbol keyword args)
|
||||
"Turn ARGS into a list of conses of (`package-name' . `install-command')."
|
||||
(use-package-as-one (symbol-name keyword) args
|
||||
(lambda (_label arg)
|
||||
(cond
|
||||
((and (listp arg) (listp (cdr arg)))
|
||||
(mapcar #'use-package-ensure-system-package-consify arg))
|
||||
(t
|
||||
(list (use-package-ensure-system-package-consify arg)))))))
|
||||
|
||||
(defun use-package-ensure-system-package-exists? (file-or-exe)
|
||||
"If variable is a string, ensure the file path exists.
|
||||
If it is a symbol, ensure the binary exist."
|
||||
(if (stringp file-or-exe)
|
||||
(file-exists-p file-or-exe)
|
||||
(executable-find (symbol-name file-or-exe))))
|
||||
|
||||
|
||||
;;;###autoload
|
||||
(defun use-package-handler/:ensure-system-package (name _keyword arg rest state)
|
||||
"Execute the handler for `:ensure-system-package' keyword in `use-package'."
|
||||
(let ((body (use-package-process-keywords name rest state)))
|
||||
(use-package-concat
|
||||
(mapcar #'(lambda (cons)
|
||||
`(unless (use-package-ensure-system-package-exists? ',(car cons))
|
||||
,(cdr cons))) arg)
|
||||
body)))
|
||||
|
||||
(add-to-list 'use-package-keywords :ensure-system-package t)
|
||||
|
||||
(provide 'use-package-ensure-system-package)
|
||||
|
||||
;;; use-package-ensure-system-package.el ends here
|
||||
206
lisp/use-package/use-package-ensure.el
Normal file
206
lisp/use-package/use-package-ensure.el
Normal file
|
|
@ -0,0 +1,206 @@
|
|||
;;; use-package-ensure.el --- Support for the :ensure and :pin keywords -*- lexical-binding: t; -*-
|
||||
|
||||
;; Copyright (C) 2012-2022 Free Software Foundation, Inc.
|
||||
|
||||
;; Author: John Wiegley <johnw@newartisans.com>
|
||||
;; Maintainer: John Wiegley <johnw@newartisans.com>
|
||||
|
||||
;; 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 3 of the License, 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 this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Commentary:
|
||||
|
||||
;; Provides support for the :ensure and :pin keywords, which is made available
|
||||
;; by default by requiring `use-package'.
|
||||
|
||||
;;; Code:
|
||||
|
||||
(require 'cl-lib)
|
||||
(require 'use-package-core)
|
||||
|
||||
(defgroup use-package-ensure nil
|
||||
"Support for :ensure and :pin keywords in `use-package' declarations."
|
||||
:group 'use-package)
|
||||
|
||||
(eval-when-compile
|
||||
(declare-function package-installed-p "package")
|
||||
(declare-function package-read-all-archive-contents "package" ()))
|
||||
|
||||
(defcustom use-package-always-ensure nil
|
||||
"Treat every package as though it had specified using `:ensure SEXP'.
|
||||
See also `use-package-defaults', which uses this value."
|
||||
:type 'sexp
|
||||
:group 'use-package-ensure)
|
||||
|
||||
(defcustom use-package-always-pin nil
|
||||
"Treat every package as though it had specified using `:pin SYM'.
|
||||
See also `use-package-defaults', which uses this value."
|
||||
:type 'symbol
|
||||
:group 'use-package-ensure)
|
||||
|
||||
(defcustom use-package-ensure-function 'use-package-ensure-elpa
|
||||
"Function that ensures a package is installed.
|
||||
This function is called with three arguments: the name of the
|
||||
package declared in the `use-package' form; the arguments passed
|
||||
to all `:ensure' keywords (always a list, even if only one); and
|
||||
the current `state' plist created by previous handlers.
|
||||
|
||||
Note that this function is called whenever `:ensure' is provided,
|
||||
even if it is nil. It is up to the function to decide on the
|
||||
semantics of the various values for `:ensure'.
|
||||
|
||||
This function should return non-nil if the package is installed.
|
||||
|
||||
The default value uses package.el to install the package."
|
||||
:type '(choice (const :tag "package.el" use-package-ensure-elpa)
|
||||
(function :tag "Custom"))
|
||||
:group 'use-package-ensure)
|
||||
|
||||
;;;; :pin
|
||||
|
||||
(defun use-package-normalize/:pin (_name keyword args)
|
||||
(use-package-only-one (symbol-name keyword) args
|
||||
#'(lambda (_label arg)
|
||||
(cond
|
||||
((stringp arg) arg)
|
||||
((use-package-non-nil-symbolp arg) (symbol-name arg))
|
||||
(t
|
||||
(use-package-error
|
||||
":pin wants an archive name (a string)"))))))
|
||||
|
||||
(eval-when-compile
|
||||
(defvar package-pinned-packages)
|
||||
(defvar package-archives))
|
||||
|
||||
(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-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 "Archive '%s' requested for package '%s' is not available"
|
||||
archive-name package))
|
||||
(unless (bound-and-true-p package--initialized)
|
||||
(package-initialize t))))
|
||||
|
||||
(defun use-package-handler/:pin (name _keyword archive-name rest state)
|
||||
(let ((body (use-package-process-keywords name rest state))
|
||||
(pin-form (if archive-name
|
||||
`(use-package-pin-package ',(use-package-as-symbol name)
|
||||
,archive-name))))
|
||||
;; Pinning should occur just before ensuring
|
||||
;; See `use-package-handler/:ensure'.
|
||||
(if (bound-and-true-p byte-compile-current-file)
|
||||
(eval pin-form) ; Eval when byte-compiling,
|
||||
(push pin-form body)) ; or else wait until runtime.
|
||||
body))
|
||||
|
||||
;;;; :ensure
|
||||
|
||||
(defvar package-archive-contents)
|
||||
|
||||
;;;###autoload
|
||||
(defun use-package-normalize/:ensure (_name keyword args)
|
||||
(if (null args)
|
||||
(list t)
|
||||
(use-package-only-one (symbol-name keyword) args
|
||||
#'(lambda (_label arg)
|
||||
(cond
|
||||
((symbolp arg)
|
||||
(list arg))
|
||||
((and (listp arg) (= 3 (length arg))
|
||||
(symbolp (nth 0 arg))
|
||||
(eq :pin (nth 1 arg))
|
||||
(or (stringp (nth 2 arg))
|
||||
(symbolp (nth 2 arg))))
|
||||
(list (cons (nth 0 arg) (nth 2 arg))))
|
||||
(t
|
||||
(use-package-error
|
||||
(concat ":ensure wants an optional package name "
|
||||
"(an unquoted symbol name), or (<symbol> :pin <string>)"))))))))
|
||||
|
||||
(defun use-package-ensure-elpa (name args _state &optional _no-refresh)
|
||||
(dolist (ensure args)
|
||||
(let ((package
|
||||
(or (and (eq ensure t) (use-package-as-symbol name))
|
||||
ensure)))
|
||||
(when package
|
||||
(require 'package)
|
||||
(when (consp package)
|
||||
(use-package-pin-package (car package) (cdr package))
|
||||
(setq package (car package)))
|
||||
(unless (package-installed-p package)
|
||||
(condition-case-unless-debug err
|
||||
(progn
|
||||
(when (assoc package (bound-and-true-p
|
||||
package-pinned-packages))
|
||||
(package-read-all-archive-contents))
|
||||
(if (assoc package package-archive-contents)
|
||||
(package-install package)
|
||||
(package-refresh-contents)
|
||||
(when (assoc package (bound-and-true-p
|
||||
package-pinned-packages))
|
||||
(package-read-all-archive-contents))
|
||||
(package-install package))
|
||||
t)
|
||||
(error
|
||||
(display-warning 'use-package
|
||||
(format "Failed to install %s: %s"
|
||||
name (error-message-string err))
|
||||
:error))))))))
|
||||
|
||||
;;;###autoload
|
||||
(defun use-package-handler/:ensure (name _keyword ensure rest state)
|
||||
(let* ((body (use-package-process-keywords name rest state)))
|
||||
;; We want to avoid installing packages when the `use-package' macro is
|
||||
;; being macro-expanded by elisp completion (see `lisp--local-variables'),
|
||||
;; but still install packages when byte-compiling, to avoid requiring
|
||||
;; `package' at runtime.
|
||||
(if (bound-and-true-p byte-compile-current-file)
|
||||
;; Eval when byte-compiling,
|
||||
(funcall use-package-ensure-function name ensure state)
|
||||
;; or else wait until runtime.
|
||||
(push `(,use-package-ensure-function ',name ',ensure ',state)
|
||||
body))
|
||||
body))
|
||||
|
||||
(add-to-list 'use-package-defaults
|
||||
'(:ensure (list use-package-always-ensure)
|
||||
(lambda (name args)
|
||||
(and use-package-always-ensure
|
||||
(not (plist-member args :load-path))))) t)
|
||||
|
||||
(add-to-list 'use-package-defaults
|
||||
'(:pin use-package-always-pin use-package-always-pin) t)
|
||||
|
||||
(add-to-list 'use-package-keywords :ensure)
|
||||
(add-to-list 'use-package-keywords :pin)
|
||||
|
||||
(provide 'use-package-ensure)
|
||||
|
||||
;;; use-package-ensure.el ends here
|
||||
70
lisp/use-package/use-package-jump.el
Normal file
70
lisp/use-package/use-package-jump.el
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
;;; use-package-jump.el --- Attempt to jump to a use-package declaration -*- lexical-binding: t; -*-
|
||||
|
||||
;; Copyright (C) 2012-2022 Free Software Foundation, Inc.
|
||||
|
||||
;; Author: John Wiegley <johnw@newartisans.com>
|
||||
;; Maintainer: John Wiegley <johnw@newartisans.com>
|
||||
|
||||
;; 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 3 of the License, 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 this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Commentary:
|
||||
|
||||
;; Provides the command `M-x use-package-jump-to-package-form', however it
|
||||
;; only works if the package being jumped to was required during
|
||||
;; initialization. If it was delay-loaded, it will not work.
|
||||
;; Improvements are needed.
|
||||
|
||||
;;; Code:
|
||||
|
||||
(require 'use-package-core)
|
||||
|
||||
(defun use-package-find-require (package)
|
||||
"Find file that required PACKAGE by searching `load-history'.
|
||||
Returns an absolute file path or nil if none is found."
|
||||
(catch 'suspect
|
||||
(dolist (filespec load-history)
|
||||
(dolist (entry (cdr filespec))
|
||||
(when (equal entry (cons 'require package))
|
||||
(throw 'suspect (car filespec)))))))
|
||||
|
||||
;;;###autoload
|
||||
(defun use-package-jump-to-package-form (package)
|
||||
"Attempt to find and jump to the `use-package' form that loaded PACKAGE.
|
||||
This will only find the form if that form actually required
|
||||
PACKAGE. If PACKAGE was previously required then this function
|
||||
will jump to the file that originally required PACKAGE instead."
|
||||
(interactive (list (completing-read "Package: " features)))
|
||||
(let* ((package (if (stringp package) (intern package) package))
|
||||
(requiring-file (use-package-find-require package))
|
||||
file location)
|
||||
(if (null requiring-file)
|
||||
(user-error "Can't find file requiring file; may have been autoloaded")
|
||||
(setq file (if (string= (file-name-extension requiring-file) "elc")
|
||||
(concat (file-name-sans-extension requiring-file) ".el")
|
||||
requiring-file))
|
||||
(when (file-exists-p file)
|
||||
(find-file-other-window file)
|
||||
(save-excursion
|
||||
(goto-char (point-min))
|
||||
(setq location
|
||||
(re-search-forward
|
||||
(format (eval use-package-form-regexp-eval) package) nil t)))
|
||||
(if (null location)
|
||||
(message "No use-package form found.")
|
||||
(goto-char location)
|
||||
(beginning-of-line))))))
|
||||
|
||||
(provide 'use-package-jump)
|
||||
|
||||
;;; use-package-jump.el ends here
|
||||
76
lisp/use-package/use-package-lint.el
Normal file
76
lisp/use-package/use-package-lint.el
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
;;; use-package-lint.el --- Attempt to find errors in use-package declarations -*- lexical-binding: t; -*-
|
||||
|
||||
;; Copyright (C) 2012-2022 Free Software Foundation, Inc.
|
||||
|
||||
;; Author: John Wiegley <johnw@newartisans.com>
|
||||
;; Maintainer: John Wiegley <johnw@newartisans.com>
|
||||
|
||||
;; 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 3 of the License, 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 this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Commentary:
|
||||
|
||||
;; Provides the command `M-x use-package-lint'.
|
||||
|
||||
;;; Code:
|
||||
|
||||
(require 'cl-lib)
|
||||
(require 'use-package-core)
|
||||
|
||||
(defun use-package-lint-declaration (name plist)
|
||||
(dolist (path (plist-get plist :load-path))
|
||||
(unless (file-exists-p path)
|
||||
(display-warning
|
||||
'use-package
|
||||
(format "%s :load-path does not exist: %s"
|
||||
name path) :error)))
|
||||
|
||||
(unless (or (plist-member plist :disabled)
|
||||
(plist-get plist :no-require)
|
||||
(locate-library (use-package-as-string name) nil
|
||||
(plist-get plist :load-path)))
|
||||
(display-warning
|
||||
'use-package
|
||||
(format "%s module cannot be located" name) :error))
|
||||
|
||||
;; (dolist (command (plist-get plist :commands))
|
||||
;; (unless (string= (find-lisp-object-file-name command nil)
|
||||
;; (locate-library (use-package-as-string name) nil
|
||||
;; (plist-get plist :load-path)))
|
||||
;; (display-warning
|
||||
;; 'use-package
|
||||
;; (format "%s :command is from different path: %s"
|
||||
;; name (symbol-name command)) :error)))
|
||||
)
|
||||
|
||||
;;;###autoload
|
||||
(defun use-package-lint ()
|
||||
"Check for errors in `use-package' declarations.
|
||||
For example, if the module's `:if' condition is met, but even
|
||||
with the specified `:load-path' the module cannot be found."
|
||||
(interactive)
|
||||
(save-excursion
|
||||
(goto-char (point-min))
|
||||
(let ((re (eval use-package-form-regexp-eval)))
|
||||
(while (re-search-forward re nil t)
|
||||
(goto-char (match-beginning 0))
|
||||
(let ((decl (read (current-buffer))))
|
||||
(when (eq (car decl) 'use-package)
|
||||
(use-package-lint-declaration
|
||||
(use-package-as-string (cadr decl))
|
||||
(use-package-normalize-keywords
|
||||
(cadr decl) (cddr decl)))))))))
|
||||
|
||||
(provide 'use-package-lint)
|
||||
|
||||
;;; use-package-lint.el ends here
|
||||
51
lisp/use-package/use-package.el
Normal file
51
lisp/use-package/use-package.el
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
;;; use-package.el --- A configuration macro for simplifying your .emacs -*- lexical-binding: t; -*-
|
||||
|
||||
;; Copyright (C) 2012-2022 Free Software Foundation, Inc.
|
||||
|
||||
;; Author: John Wiegley <johnw@newartisans.com>
|
||||
;; Maintainer: John Wiegley <johnw@newartisans.com>
|
||||
;; Created: 17 Jun 2012
|
||||
;; Version: 2.4.4
|
||||
;; Package-Requires: ((emacs "24.3") (bind-key "2.4"))
|
||||
;; Keywords: dotemacs startup speed config package extensions
|
||||
;; 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 3 of the License, 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 this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
;;; 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!
|
||||
;;
|
||||
;; Please see README.md from the same repository for documentation.
|
||||
|
||||
;;; Code:
|
||||
|
||||
(require 'use-package-core)
|
||||
|
||||
(require 'use-package-bind-key)
|
||||
(require 'use-package-diminish)
|
||||
(require 'use-package-delight)
|
||||
(require 'use-package-ensure)
|
||||
|
||||
(declare-function use-package-jump-to-package-form "use-package-jump")
|
||||
(autoload #'use-package-jump-to-package-form "use-package-jump" nil t)
|
||||
|
||||
(provide 'use-package)
|
||||
|
||||
;;; use-package.el ends here
|
||||
153
test/lisp/use-package/use-package-chords-tests.el
Normal file
153
test/lisp/use-package/use-package-chords-tests.el
Normal file
|
|
@ -0,0 +1,153 @@
|
|||
;;; use-package-chords-tests.el --- Tests for use-package-chords.el -*- lexical-binding: t; -*-
|
||||
|
||||
;; 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 3 of the License, 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 this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
;;; Code:
|
||||
|
||||
(require 'use-package)
|
||||
(require 'use-package-tests)
|
||||
(require 'use-package-chords)
|
||||
|
||||
(defmacro match-expansion (form &rest value)
|
||||
`(should (pcase (expand-minimally ,form)
|
||||
,@(mapcar #'(lambda (x) (list x t)) value))))
|
||||
|
||||
(defun use-package-test-normalize-chord (&rest args)
|
||||
(apply #'use-package-normalize-binder 'foo :chords args))
|
||||
|
||||
(ert-deftest use-package-test-normalize/:chords-1 ()
|
||||
(should (equal (use-package-test-normalize-chord
|
||||
'(("C-a" . alpha)))
|
||||
'(("C-a" . alpha)))))
|
||||
|
||||
(ert-deftest use-package-test-normalize/:chords-2 ()
|
||||
(should (equal (use-package-test-normalize-chord
|
||||
'(("C-a" . alpha)
|
||||
:map foo-map
|
||||
("C-b" . beta)))
|
||||
'(("C-a" . alpha)
|
||||
:map foo-map
|
||||
("C-b" . beta)))))
|
||||
|
||||
(ert-deftest use-package-test-normalize/:chords-3 ()
|
||||
(should (equal (use-package-test-normalize-chord
|
||||
'(:map foo-map
|
||||
("C-a" . alpha)
|
||||
("C-b" . beta)))
|
||||
'(:map foo-map
|
||||
("C-a" . alpha)
|
||||
("C-b" . beta)))))
|
||||
|
||||
(ert-deftest use-package-test/:chords-1 ()
|
||||
(match-expansion
|
||||
(use-package foo :chords ("C-k" . key1) ("C-u" . key2))
|
||||
`(progn
|
||||
(unless
|
||||
(fboundp 'key1)
|
||||
(autoload #'key1 "foo" nil t))
|
||||
(unless
|
||||
(fboundp 'key2)
|
||||
(autoload #'key2 "foo" nil t))
|
||||
(bind-chord "C-k" #'key1 nil)
|
||||
(bind-chord "C-u" #'key2 nil))))
|
||||
|
||||
(ert-deftest use-package-test/:chords-2 ()
|
||||
(match-expansion
|
||||
(use-package foo :chords (("C-k" . key1) ("C-u" . key2)))
|
||||
`(progn
|
||||
(unless (fboundp 'key1)
|
||||
(autoload #'key1 "foo" nil t))
|
||||
(unless (fboundp 'key2)
|
||||
(autoload #'key2 "foo" nil t))
|
||||
(bind-chord "C-k" #'key1 nil)
|
||||
(bind-chord "C-u" #'key2 nil))))
|
||||
|
||||
(ert-deftest use-package-test/:chords-3 ()
|
||||
(match-expansion
|
||||
(use-package foo :chords (:map my-map ("C-k" . key1) ("C-u" . key2)))
|
||||
`(progn
|
||||
(unless
|
||||
(fboundp 'key1)
|
||||
(autoload #'key1 "foo" nil t))
|
||||
(unless
|
||||
(fboundp 'key2)
|
||||
(autoload #'key2 "foo" nil t))
|
||||
(if
|
||||
(boundp 'my-map)
|
||||
(progn
|
||||
(bind-chord "C-k" #'key1 my-map)
|
||||
(bind-chord "C-u" #'key2 my-map))
|
||||
(eval-after-load 'foo
|
||||
'(progn
|
||||
(bind-chord "C-k" #'key1 my-map)
|
||||
(bind-chord "C-u" #'key2 my-map)))))))
|
||||
|
||||
(ert-deftest use-package-test/:chords-4 ()
|
||||
(should-error
|
||||
(match-expansion
|
||||
(use-package foo :chords :map my-map ("C-k" . key1) ("C-u" . key2))
|
||||
`(bind-chords :package foo))))
|
||||
|
||||
(ert-deftest use-package-test/:chords-5 ()
|
||||
(match-expansion
|
||||
(use-package foo :chords ("C-k" . key1) (:map my-map ("C-u" . key2)))
|
||||
`(progn
|
||||
(unless (fboundp 'key1)
|
||||
(autoload #'key1 "foo" nil t))
|
||||
(unless (fboundp 'key2)
|
||||
(autoload #'key2 "foo" nil t))
|
||||
(progn
|
||||
(bind-chord "C-k" #'key1 nil)
|
||||
(if
|
||||
(boundp 'my-map)
|
||||
(bind-chord "C-u" #'key2 my-map)
|
||||
(eval-after-load 'foo
|
||||
'(bind-chord "C-u" #'key2 my-map)))))))
|
||||
|
||||
(ert-deftest use-package-test/:chords-6 ()
|
||||
(match-expansion
|
||||
(use-package foo
|
||||
:chords
|
||||
("C-k" . key1)
|
||||
(:map my-map ("C-u" . key2))
|
||||
(:map my-map2 ("C-u" . key3)))
|
||||
`(progn
|
||||
(unless
|
||||
(fboundp 'key1)
|
||||
(autoload #'key1 "foo" nil t))
|
||||
(unless
|
||||
(fboundp 'key2)
|
||||
(autoload #'key2 "foo" nil t))
|
||||
(unless
|
||||
(fboundp 'key3)
|
||||
(autoload #'key3 "foo" nil t))
|
||||
(progn
|
||||
(bind-chord "C-k" #'key1 nil)
|
||||
(if
|
||||
(boundp 'my-map)
|
||||
(bind-chord "C-u" #'key2 my-map)
|
||||
(eval-after-load 'foo
|
||||
'(bind-chord "C-u" #'key2 my-map)))
|
||||
(if
|
||||
(boundp 'my-map2)
|
||||
(bind-chord "C-u" #'key3 my-map2)
|
||||
(eval-after-load 'foo
|
||||
'(bind-chord "C-u" #'key3 my-map2)))))))
|
||||
|
||||
;; Local Variables:
|
||||
;; no-byte-compile: t
|
||||
;; no-update-autoloads: t
|
||||
;; End:
|
||||
|
||||
;;; use-package-chords-tests.el ends here
|
||||
1957
test/lisp/use-package/use-package-tests.el
Normal file
1957
test/lisp/use-package/use-package-tests.el
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue