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