novice.el
is one of the most-maligned [citation needed] packages in the Emacs
ecosystem, consistently causing new and slightly-more-experienced users
puzzlement when they attempt to run a command and get the default “You have
invoked the disabled command …” message, with its confirmation dialogue and
confusing options. Sometimes, the command has been “fat-fingered,” like typing
C-x C-n
instead of C-x n
, or we’re trying to invoke the command with M-x
, which
I think means we know what we’re doing.
sophomore attempts to add a better UI around disabled commands that’s better-suited to more experienced users. Of course, my attempt might come off as only a little better than novice, or even, dare I say, “sophomoric” in nature.
This package trades in the knowledge that a command’s disabled property need not
be a binary choice between “yes” or “no”, “t” or “nil”: indeed, there are a
number of ways in which a command might be considered “disabled,” with different
safeguards against using it. For intermediate and more advanced users, a common
issue is “fat-fingering” commands like set-fill-column
when find-file
was meant,
or accidentally killing Emacs when typing C-x too quickly. In addition, in my
own usage I don’t want to disable a command per se, but disallow too-easy
invocation (which isn’t possible with the built-in novice.el
except by
unbinding or rebinding a number of keys).
Until this package is on MELPA or Non-GNU ELPA, you can install it from this Git repository. I use straight.el:
(straight-use-package '(sophomore :host github :repo "duckwork/sophomore.el"))
By default, sophomore doesn’t do anything. There are a number of entry points into its functionality, however:
(sophomore-mode +1)
Instead of a simple disabled/enabled dichotomy for commands, it can be useful to
have more options. For example, I myself frequently “fat-finger” C-x C-c
, which
can close Emacs. However, by adding (confirm . sophomore-disabled-confirm)
to
sophomore-dispatch-alist
, and running (put 'save-buffers-kill-terminal 'disabled
confirm)
(or the sophomore function (sophomore-disable-with 'confirm
#'save-buffers-kill-terminal)
), I can get a yes-or-no prompt when I fat-finger
something before running it.
sophomore-dispatch
searches through sophomore-dispatch-alist
for the symbol in a
command’s disabled property, running the function associated with it. If there
isn’t one, sophomore-dispatch-fallback-function
is called instead, which
defaults to sophomore-disabled-M-x
. That function allows calling a function
from M-x
(execute-extended-command
), but not from a key binding—so you can
still run the command, but not accidentally.
(sophomore-enable-all)
Map through every command, and if its disabled
property is non-nil, set it to
nil. This is a convenience function that you can really do yourself, and in
fact was pulled directly from EmacsWiki.
sophomore also ships with a few functions to make enabling and disabling commands in bulk easier:
sophomore-disable
- Disable all commands given as parameters by setting their
disabled
property tot
. sophomore-enable
- Enable all commands given as parameters by setting their
disabled
property tonil
. sophomore-disable-with
- Given a symbol and a list of commands, set each
command’s
disabled
property to the symbol.
As an example, here’s my personal sophomore
configuration:
(straight-use-package '(sophomore :host github :repo "duckwork/sophomore.el"))
(sophomore-mode +1)
(sophomore-disable 'confirm #'save-buffers-kill-terminal)
sophomore is licensed under the Good Choices License:
Everyone is permitted to do whatever with this software, without limitation. This software comes without any warranty whatsoever, but with two pieces of advice:
- Be kind to yourself.
- Make good choices.
To contribute, you can open an issue or pull request on this repo.
- v0.2.1
- Attempt to improve the README.
- v0.2
- Add
sophomore-mode
for easier use; change the defaultsophomore-dispatch-alist
; change some function names. - v0.1
- Initial release