# HG changeset patch
# User David Champion <[email protected]>
# Date 1385592820 21600
# Wed Nov 27 16:53:40 2013 -0600
# Node ID 44c56715ef8bb953bfda7a271a2c0544b55941cc
# Parent 3306cb186f49e83edf15aac91c51f4c6131ef8fe
add `unbind' and `unmacro' commands
This is a refresh and update of a very old (~2001) patch providing
unbind and unmacro commands. The topic has been through a lot of
controversy. Originally the unbind patch was simply a shortcut to
binding keys to noop -- unless you unbound *, in which case they
were truly unbound.
The distinction is subtle, and concerns what the correct fallback
behavior is after a key is unbound. Consider the following steps, run
with 'mutt -F/dev/null -f/dev/null'.
1. pressing 't' in the index gives a 'There are no messages' response,
because 't' is unbound in index but bound in generic to <tag-entry>.
2. enter command: bind index t help
3. pressing 't' in the index results in help
4. enter command: unbind index t
5. pressing 't' in the index results in 'Key is not bound'. There
is no fallthrough to the generic menu, because 't' is -really-
bound to <noop>.
This updated patch now does a true unbind: it removes the mapping from
the key table completely, so that step 5 becomes the same as step 1.
It also adds the capability to use '*' for any bind or macro command.
diff -r 3306cb186f49 -r 44c56715ef8b doc/manual.xml.head
--- a/doc/manual.xml.head Tue Oct 29 00:11:16 2013 -0700
+++ b/doc/manual.xml.head Wed Nov 27 16:53:40 2013 -0600
@@ -2158,7 +2158,9 @@
<para>
<emphasis>map</emphasis> specifies in which menu the binding belongs.
Multiple maps may be specified by separating them with commas (no
-additional whitespace is allowed). The currently defined maps are:
+additional whitespace is allowed). A <literal>*</literal> attempts
+to bind in all maps, but beware that not all functions are defined
+for all maps. The currently defined maps are:
</para>
<anchor id="maps"/>
@@ -4378,6 +4380,44 @@
</sect1>
+<sect1 id="unbind">
+<title>Removing key bindings</title>
+<para>Usage:</para>
+
+<cmdsynopsis>
+<command>unbind</command>
+<arg choice="plain"><replaceable class="parameter">map</replaceable></arg>
+<group choice="req">
+<arg choice="plain"><replaceable class="parameter">key</replaceable></arg>
+<arg choice="plain"><replaceable class="parameter">*</replaceable></arg>
+</group>
+</cmdsynopsis>
+
+<para>
+This command removes one or all key bindings from a set of menus.
+As with <literal>bind</literal>, multiple menus may be separated
+by commas, or a <literal>*</literal> can be used to unbind in all
+menus.
+If <literal>key</literal> is <literal>*</literal>, all bindings
+in the specified set of maps are removed.
+</para>
+
+<para>
+To prevent you from hanging yourself, <literal>unbind</literal> will
+always push the <literal>enter-command</literal> function back onto
+the Generic bindings table, bound to the <quote>:</quote> key.) A set
+of basic <literal>editor</literal> bindings is also added so that the
+<literal>enter-command</literal> prompt is actually usable, and an
+<literal>exit</literal> bindind is added to the <literal>pager</literal>
+map.
+</para>
+
+<para>
+The <literal>bind map *</literal> command will reload default bindings
+for the specified map(s), but it does not re-parse any Muttrc files.
+</para>
+</sect1>
+
<sect1 id="unhook">
<title>Removing Hooks</title>
@@ -4404,6 +4444,26 @@
</sect1>
+<sect1 id="unmacro">
+<title>Removing macros</title>
+<para>Usage:</para>
+
+<cmdsynopsis>
+<command>unmacro</command>
+<arg choice="plain"><replaceable class="parameter">map</replaceable></arg>
+<group choice="req">
+<arg choice="plain"><replaceable class="parameter">key(s)</replaceable></arg>
+<arg choice="plain"><replaceable class="parameter">*</replaceable></arg>
+</group>
+</cmdsynopsis>
+
+<para>
+<literal>Unmacro</literal> is identical to <literal>unbind</literal>,
+except that <literal>unbind</literal> operates only on single-key
+bindings, and <literal>unmacro</literal> operates only on macros.
+</para>
+</sect1>
+
<sect1 id="formatstrings">
<title>Format Strings</title>
@@ -8470,6 +8530,19 @@
<listitem>
<cmdsynopsis>
+<command><link linkend="unbind">unbind</link></command>
+<arg choice="plain">
+<replaceable class="parameter">map</replaceable>
+</arg>
+<group choice="req">
+<arg choice="plain"><replaceable class="parameter">key</replaceable></arg>
+<arg choice="plain"><replaceable class="parameter">*</replaceable></arg>
+</group>
+</cmdsynopsis>
+</listitem>
+
+<listitem>
+<cmdsynopsis>
<command><link linkend="charset-hook">charset-hook</link></command>
<arg choice="plain">
<replaceable class="parameter">alias</replaceable>
@@ -8754,6 +8827,19 @@
<listitem>
<cmdsynopsis>
+<command><link linkend="unmacro">unmacro</link></command>
+<arg choice="plain">
+<replaceable class="parameter">map</replaceable>
+</arg>
+<group choice="req">
+<arg choice="plain"><replaceable class="parameter">key(s)</replaceable></arg>
+<arg choice="plain"><replaceable class="parameter">*</replaceable></arg>
+</group>
+</cmdsynopsis>
+</listitem>
+
+<listitem>
+<cmdsynopsis>
<command><link linkend="mailboxes">mailboxes</link></command>
<arg choice="plain">
<replaceable class="parameter">mailbox</replaceable>
diff -r 3306cb186f49 -r 44c56715ef8b doc/muttrc.man.head
--- a/doc/muttrc.man.head Tue Oct 29 00:11:16 2013 -0700
+++ b/doc/muttrc.man.head Wed Nov 27 16:53:40 2013 -0600
@@ -160,11 +160,16 @@
.BR mailcap (5)
entry given for the original MIME type. For instance, you may add
the \fBapplication/octet-stream\fP MIME type to this list.
-.TP
+.PP
+.nf
\fBbind\fP \fImap1,map2,...\fP \fIkey\fP \fIfunction\fP
+\fBunbind\fP \fImap1,map2,...\fP [ \fB*\fP | \fIkey\fP ]
+.fi
+.IP
This command binds the given \fIkey\fP for the given \fImap\fP or maps
to the given \fIfunction\fP. Multiple maps may be specified by
-separating them with commas (no whitespace is allowed).
+separating them with commas (no whitespace is allowed). An asterisk
+(\fB*\fP) represents all maps.
.IP
Valid maps are:
.BR generic ", " alias ", " attach ", "
@@ -176,6 +181,17 @@
For more information on keys and functions, please consult the Mutt
Manual. Note that the function name is to be specified without
angle brackets.
+.IP
+The \fBunbind\fP command removes key bindings. Either the map
+name or the key name may be a wildcard (\fB*\fP). (To unbind the
+asterisk key itself, use \(lq\fBbind \fImap\fB * noop\fP\(rq.)
+.IP
+To prevent irreversible damage, \fBunbind\fP will always ensure that
+the \fBenter-command\fP function is bound in the \fIgeneric\fP map.
+Similarly, some basic \fIeditor\fP bindings are loaded, and an \fIexit\fP
+function is bound in the \fIpager\fP map.
+\(lq\fBbind \fImap\fB *\fP\(rq will reload all default bindings for
+the specified map(s).
.TP
\fBaccount-hook\fP [\fB!\fP]\fIregexp\fP \fIcommand\fP
This hook is executed whenever you access a remote mailbox. Useful
@@ -214,11 +230,19 @@
.IP
When several \fBfolder-hook\fPs match a given mail folder, they are
executed in the order given in the configuration file.
-.TP
+.PP
+.nf
\fBmacro\fP \fImap\fP \fIkey\fP \fIsequence\fP [ \fIdescription\fP ]
-This command binds the given \fIsequence\fP of keys to the given
+\fBunmacro\fP [ \fB*\fP | \fImap\fP ] [ \fB*\fP | \fIkey(s)\fP ]
+.fi
+.IP
+The \fBmacro\fP command binds the given \fIsequence\fP of keys to the given
\fIkey\fP in the given \fImap\fP or maps. For valid maps, see \fBbind\fP. To
specify multiple maps, put only a comma between the maps.
+.IP
+\fBunmacro\fP is identical to \fBunbind\fP, except that \fBunbind works
+only for single key bindings, and \fBunmacro\fP works only on macro
+definitions.
.PP
.nf
\fBcolor\fP \fIobject\fP \fIforeground\fP \fIbackground\fP [ \fI regexp\fP ]
diff -r 3306cb186f49 -r 44c56715ef8b init.h
--- a/init.h Tue Oct 29 00:11:16 2013 -0700
+++ b/init.h Wed Nov 27 16:53:40 2013 -0600
@@ -3599,10 +3599,12 @@
{ "unalias", parse_unalias, 0 },
{ "unalternative_order",parse_unlist, UL
&AlternativeOrderList },
{ "unauto_view", parse_unlist, UL &AutoViewList },
+ { "unbind", mutt_parse_unbind, M_UNBIND },
{ "unhdr_order", parse_unlist, UL &HeaderOrderList },
{ "unhook", mutt_parse_unhook, 0 },
{ "unignore", parse_unignore, 0 },
{ "unlists", parse_unlists, 0 },
+ { "unmacro", mutt_parse_unbind, M_UNMACRO },
{ "unmono", mutt_parse_unmono, 0 },
{ "unmy_hdr", parse_unmy_hdr, 0 },
{ "unscore", mutt_parse_unscore, 0 },
diff -r 3306cb186f49 -r 44c56715ef8b keymap.c
--- a/keymap.c Tue Oct 29 00:11:16 2013 -0700
+++ b/keymap.c Wed Nov 27 16:53:40 2013 -0600
@@ -703,119 +703,172 @@
#endif
}
-void km_init (void)
+void km_init (int menu)
{
- memset (Keymaps, 0, sizeof (struct keymap_t *) * MENU_MAX);
+ if (menu == -1)
+ memset (Keymaps, 0, sizeof (struct keymap_t *) * MENU_MAX);
+ else
+ memset (&Keymaps[menu], 0, sizeof (struct keymap_t *));
- create_bindings (OpAttach, MENU_ATTACH);
- create_bindings (OpBrowser, MENU_FOLDER);
- create_bindings (OpCompose, MENU_COMPOSE);
- create_bindings (OpMain, MENU_MAIN);
- create_bindings (OpPager, MENU_PAGER);
- create_bindings (OpPost, MENU_POST);
- create_bindings (OpQuery, MENU_QUERY);
- create_bindings (OpAlias, MENU_ALIAS);
+ /* attach menu bindings */
+ if (menu == MENU_ATTACH || menu == -1)
+ {
+ create_bindings (OpAttach, MENU_ATTACH);
+ km_bindkey ("<enter>", MENU_ATTACH, OP_VIEW_ATTACH);
+ }
+ /* browser menu bindings */
+ if (menu == MENU_FOLDER || menu == -1)
+ {
+ create_bindings (OpBrowser, MENU_FOLDER);
+ }
- if ((WithCrypto & APPLICATION_PGP))
+ /* compose menu bindings */
+ if (menu == MENU_COMPOSE || menu == -1)
+ {
+ create_bindings (OpCompose, MENU_COMPOSE);
+ km_bindkey ("<enter>", MENU_COMPOSE, OP_VIEW_ATTACH);
+
+ /* edit-to (default "t") hides generic tag-entry in Compose menu
+ This will bind tag-entry to "T" in the Compose menu */
+ km_bindkey ("T", MENU_COMPOSE, OP_TAG);
+ }
+
+ /* main menu bindings */
+ if (menu == MENU_MAIN || menu == -1)
+ {
+ create_bindings (OpMain, MENU_MAIN);
+ km_bindkey (" ", MENU_MAIN, OP_DISPLAY_MESSAGE);
+ km_bindkey ("<up>", MENU_MAIN, OP_MAIN_PREV_UNDELETED);
+ km_bindkey ("<down>", MENU_MAIN, OP_MAIN_NEXT_UNDELETED);
+ km_bindkey ("J", MENU_MAIN, OP_NEXT_ENTRY);
+ km_bindkey ("K", MENU_MAIN, OP_PREV_ENTRY);
+ km_bindkey ("x", MENU_MAIN, OP_EXIT);
+ km_bindkey ("<enter>", MENU_MAIN, OP_DISPLAY_MESSAGE);
+ }
+
+ /* pager menu bindings */
+ if (menu == MENU_PAGER || menu == -1)
+ {
+ create_bindings (OpPager, MENU_PAGER);
+ km_bindkey ("x", MENU_PAGER, OP_EXIT);
+ km_bindkey ("i", MENU_PAGER, OP_EXIT);
+ km_bindkey ("<backspace>", MENU_PAGER, OP_PREV_LINE);
+ km_bindkey ("<pagedown>", MENU_PAGER, OP_NEXT_PAGE);
+ km_bindkey ("<pageup>", MENU_PAGER, OP_PREV_PAGE);
+ km_bindkey ("<up>", MENU_PAGER, OP_MAIN_PREV_UNDELETED);
+ km_bindkey ("<right>", MENU_PAGER, OP_MAIN_NEXT_UNDELETED);
+ km_bindkey ("<down>", MENU_PAGER, OP_MAIN_NEXT_UNDELETED);
+ km_bindkey ("<left>", MENU_PAGER, OP_MAIN_PREV_UNDELETED);
+ km_bindkey ("<home>", MENU_PAGER, OP_PAGER_TOP);
+ km_bindkey ("<end>", MENU_PAGER, OP_PAGER_BOTTOM);
+ km_bindkey ("1", MENU_PAGER, OP_JUMP);
+ km_bindkey ("2", MENU_PAGER, OP_JUMP);
+ km_bindkey ("3", MENU_PAGER, OP_JUMP);
+ km_bindkey ("4", MENU_PAGER, OP_JUMP);
+ km_bindkey ("5", MENU_PAGER, OP_JUMP);
+ km_bindkey ("6", MENU_PAGER, OP_JUMP);
+ km_bindkey ("7", MENU_PAGER, OP_JUMP);
+ km_bindkey ("8", MENU_PAGER, OP_JUMP);
+ km_bindkey ("9", MENU_PAGER, OP_JUMP);
+ km_bindkey ("<enter>", MENU_PAGER, OP_NEXT_LINE);
+ }
+
+ /* post menu bindings */
+ if (menu == MENU_POST || menu == -1)
+ {
+ create_bindings (OpPost, MENU_POST);
+ }
+
+ /* query menu bindings */
+ if (menu == MENU_QUERY || menu == -1)
+ {
+ create_bindings (OpQuery, MENU_QUERY);
+ }
+
+ /* alias menu bindings */
+ if (menu == MENU_ALIAS || menu == -1)
+ {
+ create_bindings (OpAlias, MENU_ALIAS);
+ km_bindkey ("<return>", MENU_ALIAS, OP_GENERIC_SELECT_ENTRY);
+ km_bindkey ("<enter>", MENU_ALIAS, OP_GENERIC_SELECT_ENTRY);
+ km_bindkey ("<space>", MENU_ALIAS, OP_TAG);
+ }
+
+ /* pgp menu bindings */
+ if ((WithCrypto & APPLICATION_PGP) && (menu == MENU_PGP || menu == -1))
+ {
create_bindings (OpPgp, MENU_PGP);
+ }
- if ((WithCrypto & APPLICATION_SMIME))
+ /* s/mime menu bindings */
+ if ((WithCrypto & APPLICATION_SMIME) && (menu == MENU_SMIME || menu == -1))
+ {
create_bindings (OpSmime, MENU_SMIME);
+ }
#ifdef CRYPT_BACKEND_GPGME
- create_bindings (OpPgp, MENU_KEY_SELECT_PGP);
- create_bindings (OpSmime, MENU_KEY_SELECT_SMIME);
+ /* gpgme bindings */
+ if (menu == MENU_KEY_SELECT_PGP || menu == -1)
+ {
+ create_bindings (OpPgp, MENU_KEY_SELECT_PGP);
+ }
+ if (menu == MENU_KEY_SELECT_SMIME || menu == -1)
+ {
+ create_bindings (OpSmime, MENU_KEY_SELECT_SMIME);
+ }
#endif
#ifdef MIXMASTER
- create_bindings (OpMix, MENU_MIX);
+ /* mixmaster bindings */
+ if (menu == MENU_MIX || menu == -1)
+ {
+ create_bindings (OpMix, MENU_MIX);
- km_bindkey ("<space>", MENU_MIX, OP_GENERIC_SELECT_ENTRY);
- km_bindkey ("h", MENU_MIX, OP_MIX_CHAIN_PREV);
- km_bindkey ("l", MENU_MIX, OP_MIX_CHAIN_NEXT);
+ km_bindkey ("<space>", MENU_MIX, OP_GENERIC_SELECT_ENTRY);
+ km_bindkey ("h", MENU_MIX, OP_MIX_CHAIN_PREV);
+ km_bindkey ("l", MENU_MIX, OP_MIX_CHAIN_NEXT);
+ }
#endif
/* bindings for the line editor */
- create_bindings (OpEditor, MENU_EDITOR);
-
- km_bindkey ("<up>", MENU_EDITOR, OP_EDITOR_HISTORY_UP);
- km_bindkey ("<down>", MENU_EDITOR, OP_EDITOR_HISTORY_DOWN);
- km_bindkey ("<left>", MENU_EDITOR, OP_EDITOR_BACKWARD_CHAR);
- km_bindkey ("<right>", MENU_EDITOR, OP_EDITOR_FORWARD_CHAR);
- km_bindkey ("<home>", MENU_EDITOR, OP_EDITOR_BOL);
- km_bindkey ("<end>", MENU_EDITOR, OP_EDITOR_EOL);
- km_bindkey ("<backspace>", MENU_EDITOR, OP_EDITOR_BACKSPACE);
- km_bindkey ("<delete>", MENU_EDITOR, OP_EDITOR_BACKSPACE);
- km_bindkey ("\177", MENU_EDITOR, OP_EDITOR_BACKSPACE);
-
+ if (menu == MENU_EDITOR || menu == -1)
+ {
+ create_bindings (OpEditor, MENU_EDITOR);
+ km_bindkey ("<up>", MENU_EDITOR, OP_EDITOR_HISTORY_UP);
+ km_bindkey ("<down>", MENU_EDITOR, OP_EDITOR_HISTORY_DOWN);
+ km_bindkey ("<left>", MENU_EDITOR, OP_EDITOR_BACKWARD_CHAR);
+ km_bindkey ("<right>", MENU_EDITOR, OP_EDITOR_FORWARD_CHAR);
+ km_bindkey ("<home>", MENU_EDITOR, OP_EDITOR_BOL);
+ km_bindkey ("<end>", MENU_EDITOR, OP_EDITOR_EOL);
+ km_bindkey ("<backspace>", MENU_EDITOR, OP_EDITOR_BACKSPACE);
+ km_bindkey ("<delete>", MENU_EDITOR, OP_EDITOR_BACKSPACE);
+ km_bindkey ("\177", MENU_EDITOR, OP_EDITOR_BACKSPACE);
+ }
+
/* generic menu keymap */
- create_bindings (OpGeneric, MENU_GENERIC);
-
- km_bindkey ("<home>", MENU_GENERIC, OP_FIRST_ENTRY);
- km_bindkey ("<end>", MENU_GENERIC, OP_LAST_ENTRY);
- km_bindkey ("<pagedown>", MENU_GENERIC, OP_NEXT_PAGE);
- km_bindkey ("<pageup>", MENU_GENERIC, OP_PREV_PAGE);
- km_bindkey ("<right>", MENU_GENERIC, OP_NEXT_PAGE);
- km_bindkey ("<left>", MENU_GENERIC, OP_PREV_PAGE);
- km_bindkey ("<up>", MENU_GENERIC, OP_PREV_ENTRY);
- km_bindkey ("<down>", MENU_GENERIC, OP_NEXT_ENTRY);
- km_bindkey ("1", MENU_GENERIC, OP_JUMP);
- km_bindkey ("2", MENU_GENERIC, OP_JUMP);
- km_bindkey ("3", MENU_GENERIC, OP_JUMP);
- km_bindkey ("4", MENU_GENERIC, OP_JUMP);
- km_bindkey ("5", MENU_GENERIC, OP_JUMP);
- km_bindkey ("6", MENU_GENERIC, OP_JUMP);
- km_bindkey ("7", MENU_GENERIC, OP_JUMP);
- km_bindkey ("8", MENU_GENERIC, OP_JUMP);
- km_bindkey ("9", MENU_GENERIC, OP_JUMP);
-
- km_bindkey ("<enter>", MENU_GENERIC, OP_GENERIC_SELECT_ENTRY);
-
- /* Miscellaneous extra bindings */
-
- km_bindkey (" ", MENU_MAIN, OP_DISPLAY_MESSAGE);
- km_bindkey ("<up>", MENU_MAIN, OP_MAIN_PREV_UNDELETED);
- km_bindkey ("<down>", MENU_MAIN, OP_MAIN_NEXT_UNDELETED);
- km_bindkey ("J", MENU_MAIN, OP_NEXT_ENTRY);
- km_bindkey ("K", MENU_MAIN, OP_PREV_ENTRY);
- km_bindkey ("x", MENU_MAIN, OP_EXIT);
-
- km_bindkey ("<enter>", MENU_MAIN, OP_DISPLAY_MESSAGE);
-
- km_bindkey ("x", MENU_PAGER, OP_EXIT);
- km_bindkey ("i", MENU_PAGER, OP_EXIT);
- km_bindkey ("<backspace>", MENU_PAGER, OP_PREV_LINE);
- km_bindkey ("<pagedown>", MENU_PAGER, OP_NEXT_PAGE);
- km_bindkey ("<pageup>", MENU_PAGER, OP_PREV_PAGE);
- km_bindkey ("<up>", MENU_PAGER, OP_MAIN_PREV_UNDELETED);
- km_bindkey ("<right>", MENU_PAGER, OP_MAIN_NEXT_UNDELETED);
- km_bindkey ("<down>", MENU_PAGER, OP_MAIN_NEXT_UNDELETED);
- km_bindkey ("<left>", MENU_PAGER, OP_MAIN_PREV_UNDELETED);
- km_bindkey ("<home>", MENU_PAGER, OP_PAGER_TOP);
- km_bindkey ("<end>", MENU_PAGER, OP_PAGER_BOTTOM);
- km_bindkey ("1", MENU_PAGER, OP_JUMP);
- km_bindkey ("2", MENU_PAGER, OP_JUMP);
- km_bindkey ("3", MENU_PAGER, OP_JUMP);
- km_bindkey ("4", MENU_PAGER, OP_JUMP);
- km_bindkey ("5", MENU_PAGER, OP_JUMP);
- km_bindkey ("6", MENU_PAGER, OP_JUMP);
- km_bindkey ("7", MENU_PAGER, OP_JUMP);
- km_bindkey ("8", MENU_PAGER, OP_JUMP);
- km_bindkey ("9", MENU_PAGER, OP_JUMP);
-
- km_bindkey ("<enter>", MENU_PAGER, OP_NEXT_LINE);
-
- km_bindkey ("<return>", MENU_ALIAS, OP_GENERIC_SELECT_ENTRY);
- km_bindkey ("<enter>", MENU_ALIAS, OP_GENERIC_SELECT_ENTRY);
- km_bindkey ("<space>", MENU_ALIAS, OP_TAG);
-
- km_bindkey ("<enter>", MENU_ATTACH, OP_VIEW_ATTACH);
- km_bindkey ("<enter>", MENU_COMPOSE, OP_VIEW_ATTACH);
-
- /* edit-to (default "t") hides generic tag-entry in Compose menu
- This will bind tag-entry to "T" in the Compose menu */
- km_bindkey ("T", MENU_COMPOSE, OP_TAG);
+ if (menu == MENU_GENERIC || menu == -1)
+ {
+ create_bindings (OpGeneric, MENU_GENERIC);
+ km_bindkey ("<home>", MENU_GENERIC, OP_FIRST_ENTRY);
+ km_bindkey ("<end>", MENU_GENERIC, OP_LAST_ENTRY);
+ km_bindkey ("<pagedown>", MENU_GENERIC, OP_NEXT_PAGE);
+ km_bindkey ("<pageup>", MENU_GENERIC, OP_PREV_PAGE);
+ km_bindkey ("<right>", MENU_GENERIC, OP_NEXT_PAGE);
+ km_bindkey ("<left>", MENU_GENERIC, OP_PREV_PAGE);
+ km_bindkey ("<up>", MENU_GENERIC, OP_PREV_ENTRY);
+ km_bindkey ("<down>", MENU_GENERIC, OP_NEXT_ENTRY);
+ km_bindkey ("1", MENU_GENERIC, OP_JUMP);
+ km_bindkey ("2", MENU_GENERIC, OP_JUMP);
+ km_bindkey ("3", MENU_GENERIC, OP_JUMP);
+ km_bindkey ("4", MENU_GENERIC, OP_JUMP);
+ km_bindkey ("5", MENU_GENERIC, OP_JUMP);
+ km_bindkey ("6", MENU_GENERIC, OP_JUMP);
+ km_bindkey ("7", MENU_GENERIC, OP_JUMP);
+ km_bindkey ("8", MENU_GENERIC, OP_JUMP);
+ km_bindkey ("9", MENU_GENERIC, OP_JUMP);
+ km_bindkey ("<enter>", MENU_GENERIC, OP_GENERIC_SELECT_ENTRY);
+ }
}
void km_error_key (int menu)
@@ -860,7 +913,7 @@
}
/* expects to see: <menu-string>,<menu-string>,... <key-string> */
-static char *parse_keymap (int *menu, BUFFER *s, int maxmenus, int *nummenus,
BUFFER *err)
+static char *parse_keymap (int *menu, BUFFER *s, int maxmenus, int *nummenus,
BUFFER *err, int isunbind)
{
BUFFER buf;
int i=0;
@@ -873,7 +926,13 @@
p = buf.data;
if (MoreArgs (s))
{
- while (i < maxmenus)
+ if (!strcmp(p, "*"))
+ {
+ /* choose all menus */
+ for (i = 0; i < maxmenus; i++)
+ menu[i] = i;
+ }
+ else while (i < maxmenus)
{
q = strchr(p,',');
if (q)
@@ -891,14 +950,15 @@
break;
}
*nummenus=i;
+
/* key sequence */
mutt_extract_token (&buf, s, 0);
-
if (!*buf.data)
{
strfcpy (err->data, _("null key sequence"), err->dsize);
}
- else if (MoreArgs (s))
+ /* unbind and "bind map *" do not require more args */
+ else if (isunbind || !mutt_strcmp(buf.data, "*") || MoreArgs (s))
return (buf.data);
}
else
@@ -976,9 +1036,24 @@
int menu[sizeof(Menus)/sizeof(struct mapping_t)-1], r = 0, nummenus, i;
if ((key = parse_keymap (menu, s, sizeof (menu)/sizeof (menu[0]),
- &nummenus, err)) == NULL)
+ &nummenus, err, FALSE)) == NULL)
return (-1);
+ if (!MoreArgs (s) && mutt_strcmp(key, "*") == 0)
+ {
+ /* Reinitialize selected menus */
+ for (i = 0; i < nummenus; i++)
+ {
+ if (menu[i] != -1)
+ {
+ dprint(1, (debugfile, "bind %s *\n", mutt_getnamebyvalue(menu[i],
Menus)));
+ km_init(menu[i]);
+ }
+ }
+ FREE (&key);
+ return (r);
+ }
+
/* function to execute */
mutt_extract_token (buf, s, 0);
if (MoreArgs (s))
@@ -1016,6 +1091,127 @@
return (r);
}
+static int keycmp(keycode_t *code, char *keys, int codelen)
+{
+ keycode_t buf[MAX_SEQ];
+ int i, len;
+
+ len = parsekeys (keys, buf, MAX_SEQ);
+ for (i = 0; i < codelen && i < len && code[i] == buf[i]; i++);
+ if (i == codelen)
+ return 0;
+ return (code[i] < buf[i]) ? -1 : 1;
+}
+
+
+static void km_unbind(struct keymap_t **map, char *key, unsigned long mode)
+{
+ struct keymap_t *cur, *next, *first, *prev;
+
+ prev = NULL;
+ next = first = *map;
+
+ while ((cur = next))
+ {
+ next = cur->next;
+ if ((mode & M_UNBIND) && cur->macro != NULL)
+ {
+ prev = cur;
+ continue;
+ }
+
+ if ((mode & M_UNMACRO) && cur->macro == NULL)
+ {
+ prev = cur;
+ continue;
+ }
+
+ if (key == NULL || keycmp(cur->keys, key, cur->len) == 0)
+ {
+ FREE(&cur->macro);
+ FREE(&cur->keys);
+ FREE(&cur->descr);
+ FREE(&cur);
+
+ if (prev)
+ prev->next = next;
+ else
+ first = next;
+ }
+
+ else
+ prev = cur;
+ }
+
+ *map = first;
+}
+
+/* unbind menu-name '<key_sequence>' */
+/* Never unbind *everything*. Leave an escape hatch. */
+int mutt_parse_unbind (BUFFER *buf, BUFFER *s, unsigned long data, BUFFER *err)
+{
+ char *key;
+ int menu[sizeof(Menus)/sizeof(struct mapping_t)-1], r = 0, nummenus, i;
+
+ if ((key = parse_keymap (menu, s, sizeof (menu)/sizeof (menu[0]),
+ &nummenus, err, TRUE)) == NULL)
+ return (-1);
+
+ if (MoreArgs (s))
+ {
+ strfcpy (err->data, _("unbind: too many arguments"), err->dsize);
+ FREE (&key);
+ return (-1);
+ }
+
+ if (mutt_strcmp(key, "*") == 0)
+ {
+ int neededitorbindings = 0;
+
+ /* Unbind all in selected menus */
+ for (i = 0; i < nummenus; ++i)
+ {
+ if (menu[i] == -1)
+ continue;
+ dprint(1, (debugfile, "unbind %s %s\n", mutt_getnamebyvalue(menu[i],
Menus), key));
+ km_unbind (&Keymaps[menu[i]], NULL, data);
+
+ /* If we unbound * in generic, then rebind <enter-command> */
+ if ((menu[i] == MENU_GENERIC) && ((data & M_UNBIND) == M_UNBIND))
+ {
+ neededitorbindings++;
+ km_bindkey (":", MENU_GENERIC, OP_ENTER_COMMAND);
+ }
+
+ /* <enter-command> will need basic editor mappings.
+ * If editor bindings were removed, remember that. */
+ if (menu[i] == MENU_EDITOR)
+ neededitorbindings++;
+
+ /* pager needs at least an exit */
+ if (menu[i] == MENU_PAGER)
+ km_bindkey ("q", MENU_PAGER, OP_EXIT);
+ }
+ if (neededitorbindings == 2)
+ create_bindings (OpEditor, MENU_EDITOR);
+ }
+ else
+ {
+ /* Unbind designated key in each selected menu. */
+ for (i = 0; i < nummenus; ++i)
+ {
+ if (menu[i] != -1)
+ {
+ dprint(1, (debugfile, "unbind %s %s\n", mutt_getnamebyvalue(menu[i],
Menus), key));
+ km_unbind (&Keymaps[menu[i]], key, data);
+ }
+ }
+ }
+
+ FREE (&key);
+ return (r);
+}
+
/* macro <menu> <key> <macro> <description> */
int mutt_parse_macro (BUFFER *buf, BUFFER *s, unsigned long data, BUFFER *err)
{
@@ -1023,7 +1219,7 @@
char *seq = NULL;
char *key;
- if ((key = parse_keymap (menu, s, sizeof (menu) / sizeof (menu[0]),
&nummenus, err)) == NULL)
+ if ((key = parse_keymap (menu, s, sizeof (menu) / sizeof (menu[0]),
&nummenus, err, FALSE)) == NULL)
return (-1);
mutt_extract_token (buf, s, M_TOKEN_CONDENSE);
diff -r 3306cb186f49 -r 44c56715ef8b keymap.h
--- a/keymap.h Tue Oct 29 00:11:16 2013 -0700
+++ b/keymap.h Wed Nov 27 16:53:40 2013 -0600
@@ -47,7 +47,7 @@
int km_expand_key (char *, size_t, struct keymap_t *);
struct keymap_t *km_find_func (int, int);
-void km_init (void);
+void km_init (int);
void km_error_key (int);
void mutt_what_key (void);
diff -r 3306cb186f49 -r 44c56715ef8b main.c
--- a/main.c Tue Oct 29 00:11:16 2013 -0700
+++ b/main.c Wed Nov 27 16:53:40 2013 -0600
@@ -511,7 +511,7 @@
static void start_curses (void)
{
- km_init (); /* must come before mutt_init */
+ km_init (-1); /* must come before mutt_init */
#ifdef USE_SLANG_CURSES
SLtt_Ignore_Beep = 1; /* don't do that #*$@^! annoying visual beep! */
diff -r 3306cb186f49 -r 44c56715ef8b mutt.h
--- a/mutt.h Tue Oct 29 00:11:16 2013 -0700
+++ b/mutt.h Wed Nov 27 16:53:40 2013 -0600
@@ -955,6 +955,10 @@
#define M_PARTS_TOPLEVEL (1<<0) /* is the top-level part */
+/* Options for mutt_parse_unbind */
+#define M_UNBIND 1<<0
+#define M_UNMACRO 1<<1
+
#include "ascii.h"
#include "protos.h"
#include "lib.h"
diff -r 3306cb186f49 -r 44c56715ef8b protos.h
--- a/protos.h Tue Oct 29 00:11:16 2013 -0700
+++ b/protos.h Wed Nov 27 16:53:40 2013 -0600
@@ -326,6 +326,7 @@
int mutt_needs_mailcap (BODY *);
int mutt_num_postponed (int);
int mutt_parse_bind (BUFFER *, BUFFER *, unsigned long, BUFFER *);
+int mutt_parse_unbind (BUFFER *, BUFFER *, unsigned long, BUFFER *);
int mutt_parse_exec (BUFFER *, BUFFER *, unsigned long, BUFFER *);
int mutt_parse_color (BUFFER *, BUFFER *, unsigned long, BUFFER *);
int mutt_parse_uncolor (BUFFER *, BUFFER *, unsigned long, BUFFER *);