1 /**
2 * @file
3 * Definitions of NeoMutt commands
4 *
5 * @authors
6 * Copyright (C) 1996-2002,2007,2010,2012-2013,2016 Michael R. Elkins <me@mutt.org>
7 * Copyright (C) 2004 g10 Code GmbH
8 *
9 * @copyright
10 * This program is free software: you can redistribute it and/or modify it under
11 * the terms of the GNU General Public License as published by the Free Software
12 * Foundation, either version 2 of the License, or (at your option) any later
13 * version.
14 *
15 * This program is distributed in the hope that it will be useful, but WITHOUT
16 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
18 * details.
19 *
20 * You should have received a copy of the GNU General Public License along with
21 * this program. If not, see <http://www.gnu.org/licenses/>.
22 */
23
24 /**
25 * @page neo_mutt_commands Definitions of NeoMutt commands
26 *
27 * Definitions of NeoMutt commands
28 */
29
30 #include "config.h"
31 #include <stddef.h>
32 #include <string.h>
33 #include "address/lib.h"
34 #include "config/lib.h"
35 #include "email/lib.h"
36 #include "core/lib.h"
37 #include "alias/lib.h"
38 #include "mutt.h"
39 #include "mutt_commands.h"
40 #include "color/lib.h"
41 #include "command_parse.h"
42 #include "hook.h"
43 #include "keymap.h"
44 #include "mutt_globals.h"
45 #include "score.h"
46
47 static const struct Command mutt_commands[] = {
48 // clang-format off
49 { "account-hook", mutt_parse_hook, MUTT_ACCOUNT_HOOK },
50 { "alias", parse_alias, 0 },
51 { "alternates", parse_alternates, 0 },
52 { "alternative_order", parse_stailq, IP &AlternativeOrderList },
53 { "attachments", parse_attachments, 0 },
54 { "auto_view", parse_stailq, IP &AutoViewList },
55 { "bind", mutt_parse_bind, 0 },
56 { "cd", parse_cd, 0 },
57 { "charset-hook", mutt_parse_hook, MUTT_CHARSET_HOOK },
58 { "color", mutt_parse_color, 0 },
59 { "crypt-hook", mutt_parse_hook, MUTT_CRYPT_HOOK },
60 { "echo", parse_echo, 0 },
61 { "exec", mutt_parse_exec, 0 },
62 { "fcc-hook", mutt_parse_hook, MUTT_FCC_HOOK },
63 { "fcc-save-hook", mutt_parse_hook, MUTT_FCC_HOOK | MUTT_SAVE_HOOK },
64 { "finish", parse_finish, 0 },
65 { "folder-hook", mutt_parse_hook, MUTT_FOLDER_HOOK },
66 { "group", parse_group, MUTT_GROUP },
67 { "hdr_order", parse_stailq, IP &HeaderOrderList },
68 { "iconv-hook", mutt_parse_hook, MUTT_ICONV_HOOK },
69 { "ifdef", parse_ifdef, 0 },
70 { "ifndef", parse_ifdef, 1 },
71 { "ignore", parse_ignore, 0 },
72 { "index-format-hook", mutt_parse_idxfmt_hook, 0 },
73 { "lists", parse_lists, 0 },
74 { "macro", mutt_parse_macro, 0 },
75 { "mailboxes", parse_mailboxes, 0 },
76 { "mailto_allow", parse_stailq, IP &MailToAllow },
77 { "mbox-hook", mutt_parse_hook, MUTT_MBOX_HOOK },
78 { "message-hook", mutt_parse_hook, MUTT_MESSAGE_HOOK },
79 { "mime_lookup", parse_stailq, IP &MimeLookupList },
80 { "mono", mutt_parse_mono, 0 },
81 { "my_hdr", parse_my_hdr, 0 },
82 { "named-mailboxes", parse_mailboxes, MUTT_NAMED },
83 { "nospam", parse_spam_list, MUTT_NOSPAM },
84 { "pgp-hook", mutt_parse_hook, MUTT_CRYPT_HOOK },
85 { "push", mutt_parse_push, 0 },
86 { "reply-hook", mutt_parse_hook, MUTT_REPLY_HOOK },
87 { "reset", parse_set, MUTT_SET_RESET },
88 { "save-hook", mutt_parse_hook, MUTT_SAVE_HOOK },
89 { "score", mutt_parse_score, 0 },
90 { "send-hook", mutt_parse_hook, MUTT_SEND_HOOK },
91 { "send2-hook", mutt_parse_hook, MUTT_SEND2_HOOK },
92 { "set", parse_set, MUTT_SET_SET },
93 { "setenv", parse_setenv, MUTT_SET_SET },
94 { "shutdown-hook", mutt_parse_hook, MUTT_SHUTDOWN_HOOK | MUTT_GLOBAL_HOOK },
95 { "source", parse_source, 0 },
96 { "spam", parse_spam_list, MUTT_SPAM },
97 { "startup-hook", mutt_parse_hook, MUTT_STARTUP_HOOK | MUTT_GLOBAL_HOOK },
98 { "subjectrx", parse_subjectrx_list, 0 },
99 { "subscribe", parse_subscribe, 0 },
100 { "tag-formats", parse_tag_formats, 0 },
101 { "tag-transforms", parse_tag_transforms, 0 },
102 { "timeout-hook", mutt_parse_hook, MUTT_TIMEOUT_HOOK | MUTT_GLOBAL_HOOK },
103 { "toggle", parse_set, MUTT_SET_INV },
104 { "unalias", parse_unalias, 0 },
105 { "unalternates", parse_unalternates, 0 },
106 { "unalternative_order", parse_unstailq, IP &AlternativeOrderList },
107 { "unattachments", parse_unattachments, 0 },
108 { "unauto_view", parse_unstailq, IP &AutoViewList },
109 { "unbind", mutt_parse_unbind, MUTT_UNBIND },
110 { "uncolor", mutt_parse_uncolor, 0 },
111 { "ungroup", parse_group, MUTT_UNGROUP },
112 { "unhdr_order", parse_unstailq, IP &HeaderOrderList },
113 { "unhook", mutt_parse_unhook, 0 },
114 { "unignore", parse_unignore, 0 },
115 { "unlists", parse_unlists, 0 },
116 { "unmacro", mutt_parse_unbind, MUTT_UNMACRO },
117 { "unmailboxes", parse_unmailboxes, 0 },
118 { "unmailto_allow", parse_unstailq, IP &MailToAllow },
119 { "unmime_lookup", parse_unstailq, IP &MimeLookupList },
120 { "unmono", mutt_parse_unmono, 0 },
121 { "unmy_hdr", parse_unmy_hdr, 0 },
122 { "unscore", mutt_parse_unscore, 0 },
123 { "unset", parse_set, MUTT_SET_UNSET },
124 { "unsetenv", parse_setenv, MUTT_SET_UNSET },
125 { "unsubjectrx", parse_unsubjectrx_list, 0 },
126 { "unsubscribe", parse_unsubscribe, 0 },
127 // clang-format on
128 };
129
130 ARRAY_HEAD(, struct Command) commands = ARRAY_HEAD_INITIALIZER;
131
132 /**
133 * mutt_commands_init - Initialize commands array and register default commands
134 */
mutt_commands_init(void)135 void mutt_commands_init(void)
136 {
137 ARRAY_RESERVE(&commands, 100);
138 COMMANDS_REGISTER(mutt_commands);
139 }
140
141 /**
142 * commands_cmp - Compare two commands by name - Implements ::sort_t - @ingroup sort_api
143 */
commands_cmp(const void * a,const void * b)144 int commands_cmp(const void *a, const void *b)
145 {
146 struct Command x = *(const struct Command *) a;
147 struct Command y = *(const struct Command *) b;
148
149 return strcmp(x.name, y.name);
150 }
151
152 /**
153 * commands_register - Add commands to Commands array
154 * @param cmds Array of Commands
155 * @param num_cmds Number of Commands in the Array
156 */
commands_register(const struct Command * cmds,const size_t num_cmds)157 void commands_register(const struct Command *cmds, const size_t num_cmds)
158 {
159 for (int i = 0; i < num_cmds; i++)
160 {
161 ARRAY_ADD(&commands, cmds[i]);
162 }
163 ARRAY_SORT(&commands, commands_cmp);
164 }
165
166 /**
167 * mutt_commands_free - Free Commands array
168 */
mutt_commands_free(void)169 void mutt_commands_free(void)
170 {
171 ARRAY_FREE(&commands);
172 }
173
174 /**
175 * mutt_commands_array - Get Commands array
176 * @param first Set to first element of Commands array
177 * @retval size_t Size of Commands array
178 */
mutt_commands_array(struct Command ** first)179 size_t mutt_commands_array(struct Command **first)
180 {
181 *first = ARRAY_FIRST(&commands);
182 return ARRAY_SIZE(&commands);
183 }
184
185 /**
186 * mutt_command_get - Get a Command by its name
187 * @param s Command string to lookup
188 * @retval ptr Success, Command
189 * @retval NULL Error, no such command
190 */
mutt_command_get(const char * s)191 struct Command *mutt_command_get(const char *s)
192 {
193 struct Command *cmd = NULL;
194 ARRAY_FOREACH(cmd, &commands)
195 {
196 if (mutt_str_equal(s, cmd->name))
197 return cmd;
198 }
199 return NULL;
200 }
201
202 #ifdef USE_LUA
203 /**
204 * mutt_commands_apply - Run a callback function on every Command
205 * @param data Data to pass to the callback function
206 * @param application Callback function
207 *
208 * This is used by Lua to expose all of NeoMutt's Commands.
209 */
mutt_commands_apply(void * data,void (* application)(void *,const struct Command *))210 void mutt_commands_apply(void *data, void (*application)(void *, const struct Command *))
211 {
212 struct Command *cmd = NULL;
213 ARRAY_FOREACH(cmd, &commands)
214 {
215 application(data, cmd);
216 }
217 }
218 #endif
219