• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

neomutt / neomutt / 13105795175

03 Feb 2025 12:35AM UTC coverage: 49.467% (-0.003%) from 49.47%
13105795175

push

github

flatcap
refactor key binding dump functions

Refactor the shared code between <help>, :bind and :macro

8904 of 18000 relevant lines covered (49.47%)

237.52 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/pattern/dlg_pattern.c
1
/**
2
 * @file
3
 * Pattern Selection Dialog
4
 *
5
 * @authors
6
 * Copyright (C) 2019 Pietro Cerutti <gahr@gahr.ch>
7
 * Copyright (C) 2020-2024 Richard Russon <rich@flatcap.org>
8
 * Copyright (C) 2023-2024 Tóth János <gomba007@gmail.com>
9
 *
10
 * @copyright
11
 * This program is free software: you can redistribute it and/or modify it under
12
 * the terms of the GNU General Public License as published by the Free Software
13
 * Foundation, either version 2 of the License, or (at your option) any later
14
 * version.
15
 *
16
 * This program is distributed in the hope that it will be useful, but WITHOUT
17
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
18
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
19
 * details.
20
 *
21
 * You should have received a copy of the GNU General Public License along with
22
 * this program.  If not, see <http://www.gnu.org/licenses/>.
23
 */
24

25
/**
26
 * @page pattern_dlg_pattern Pattern Selection Dialog
27
 *
28
 * The Pattern Selection Dialog lets the user select a pattern.
29
 *
30
 * This is a @ref gui_simple
31
 *
32
 * ## Windows
33
 *
34
 * | Name                     | Type           | See Also      |
35
 * | :----------------------- | :------------- | :------------ |
36
 * | Pattern Selection Dialog | WT_DLG_PATTERN | dlg_pattern() |
37
 *
38
 * **Parent**
39
 * - @ref gui_dialog
40
 *
41
 * **Children**
42
 * - See: @ref gui_simple
43
 *
44
 * ## Data
45
 * - #Menu
46
 * - #Menu::mdata
47
 * - #PatternEntry
48
 *
49
 * The @ref gui_simple holds a Menu.  The Pattern Selection Dialog stores its
50
 * data (#PatternEntry) in Menu::mdata.
51
 *
52
 * ## Events
53
 *
54
 * Once constructed, it is controlled by the following events:
55
 *
56
 * | Event Type  | Handler                   |
57
 * | :---------- | :------------------------ |
58
 * | #NT_CONFIG  | pattern_config_observer() |
59
 * | #NT_WINDOW  | pattern_window_observer() |
60
 *
61
 * The Pattern Selection Dialog doesn't have any specific colours, so it
62
 * doesn't need to support #NT_COLOR.
63
 *
64
 * The Pattern Selection Dialog does not implement MuttWindow::recalc() or
65
 * MuttWindow::repaint().
66
 *
67
 * Some other events are handled by the @ref gui_simple.
68
 */
69

70
#include "config.h"
71
#include <stdbool.h>
72
#include <stddef.h>
73
#include "private.h"
74
#include "mutt/lib.h"
75
#include "config/lib.h"
76
#include "core/lib.h"
77
#include "gui/lib.h"
78
#include "lib.h"
79
#include "expando/lib.h"
80
#include "key/lib.h"
81
#include "menu/lib.h"
82
#include "expando.h"
83
#include "functions.h"
84
#include "globals.h"
85
#include "mutt_logging.h"
86
#include "pattern_data.h"
87

88
/// Help Bar for the Pattern selection dialog
89
static const struct Mapping PatternHelp[] = {
90
  // clang-format off
91
  { N_("Exit"),   OP_EXIT },
92
  { N_("Select"), OP_GENERIC_SELECT_ENTRY },
93
  { N_("Help"),   OP_HELP },
94
  { NULL, 0 },
95
  // clang-format on
96
};
97

98
/**
99
 * pattern_make_entry - Create a Pattern for the Menu - Implements Menu::make_entry() - @ingroup menu_make_entry
100
 *
101
 * @sa $pattern_format
102
 */
103
static int pattern_make_entry(struct Menu *menu, int line, int max_cols, struct Buffer *buf)
×
104
{
105
  struct PatternData *pd = menu->mdata;
×
106

107
  struct PatternEntry *entry = ARRAY_GET(&pd->entries, line);
×
108

109
  const bool c_arrow_cursor = cs_subset_bool(menu->sub, "arrow_cursor");
×
110
  if (c_arrow_cursor)
×
111
  {
112
    const char *const c_arrow_string = cs_subset_string(menu->sub, "arrow_string");
×
113
    if (max_cols > 0)
×
114
      max_cols -= (mutt_strwidth(c_arrow_string) + 1);
×
115
  }
116

117
  const struct Expando *c_pattern_format = cs_subset_expando(NeoMutt->sub, "pattern_format");
×
118
  return expando_filter(c_pattern_format, PatternRenderCallbacks, entry,
×
119
                        MUTT_FORMAT_ARROWCURSOR, max_cols, EnvList, buf);
120
}
121

122
/**
123
 * create_pattern_entries - Create the Pattern Entries
124
 * @param pea Pattern Entry Array to fill
125
 */
126
static void create_pattern_entries(struct PatternEntryArray *pea)
×
127
{
128
  int num_entries = 0;
129
  while (Flags[num_entries].tag != 0)
×
130
    num_entries++;
×
131

132
  /* Add three more hard-coded entries */
133
  ARRAY_RESERVE(pea, num_entries + 3);
×
134

135
  struct Buffer *buf = buf_pool_get();
×
136

137
  struct PatternEntry entry = { 0 };
138
  for (int i = 0; Flags[i].tag != '\0'; i++)
×
139
  {
140
    entry.num = i + 1;
×
141

142
    buf_printf(buf, "~%c", Flags[i].tag);
×
143
    entry.tag = buf_strdup(buf);
×
144

145
    switch (Flags[i].eat_arg)
×
146
    {
147
      case EAT_REGEX:
×
148
        /* L10N:
149
           Pattern Completion Menu argument type: a regular expression
150
        */
151
        buf_add_printf(buf, " %s", _("EXPR"));
×
152
        break;
×
153
      case EAT_RANGE:
×
154
      case EAT_MESSAGE_RANGE:
155
        /* L10N:
156
           Pattern Completion Menu argument type: a numeric range.
157
           Used by ~m, ~n, ~X, ~z.
158
        */
159
        buf_add_printf(buf, " %s", _("RANGE"));
×
160
        break;
×
161
      case EAT_DATE:
×
162
        /* L10N:
163
           Pattern Completion Menu argument type: a date range
164
           Used by ~d, ~r.
165
        */
166
        buf_add_printf(buf, " %s", _("DATERANGE"));
×
167
        break;
×
168
      case EAT_QUERY:
×
169
        /* L10N:
170
           Pattern Completion Menu argument type: a query
171
           Used by ~I.
172
        */
173
        buf_add_printf(buf, " %s", _("QUERY"));
×
174
        break;
×
175
      default:
176
        break;
177
    }
178

179
    entry.expr = buf_strdup(buf);
×
180
    entry.desc = mutt_str_dup(_(Flags[i].desc));
×
181

182
    ARRAY_ADD(pea, entry);
×
183
  }
184

185
  /* Add struct MuttThread patterns manually.
186
   * Note we allocated 3 extra slots for these above. */
187

188
  /* L10N:
189
     Pattern Completion Menu argument type: a nested pattern.
190
     Used by ~(), ~<(), ~>().
191
  */
192
  const char *patternstr = _("PATTERN");
×
193

194
  entry.num = ARRAY_SIZE(pea) + 1;
×
195
  entry.tag = mutt_str_dup("~()");
×
196
  buf_printf(buf, "~(%s)", patternstr);
×
197
  entry.expr = buf_strdup(buf);
×
198
  // L10N: Pattern Completion Menu description for ~()
199
  entry.desc = mutt_str_dup(_("messages in threads containing messages matching PATTERN"));
×
200
  ARRAY_ADD(pea, entry);
×
201

202
  entry.num = ARRAY_SIZE(pea) + 1;
×
203
  entry.tag = mutt_str_dup("~<()");
×
204
  buf_printf(buf, "~<(%s)", patternstr);
×
205
  entry.expr = buf_strdup(buf);
×
206
  // L10N: Pattern Completion Menu description for ~<()
207
  entry.desc = mutt_str_dup(_("messages whose immediate parent matches PATTERN"));
×
208
  ARRAY_ADD(pea, entry);
×
209

210
  entry.num = ARRAY_SIZE(pea) + 1;
×
211
  entry.tag = mutt_str_dup("~>()");
×
212
  buf_printf(buf, "~>(%s)", patternstr);
×
213
  entry.expr = buf_strdup(buf);
×
214
  // L10N: Pattern Completion Menu description for ~>()
215
  entry.desc = mutt_str_dup(_("messages having an immediate child matching PATTERN"));
×
216
  ARRAY_ADD(pea, entry);
×
217

218
  buf_pool_release(&buf);
×
219
}
×
220

221
/**
222
 * pattern_config_observer - Notification that a Config Variable has changed - Implements ::observer_t - @ingroup observer_api
223
 *
224
 * The Address Book Window is affected by changes to `$sort_pattern`.
225
 */
226
static int pattern_config_observer(struct NotifyCallback *nc)
×
227
{
228
  if (nc->event_type != NT_CONFIG)
×
229
    return 0;
230
  if (!nc->global_data || !nc->event_data)
×
231
    return -1;
232

233
  struct EventConfig *ev_c = nc->event_data;
234

235
  if (!mutt_str_equal(ev_c->name, "pattern_format"))
×
236
    return 0;
237

238
  struct Menu *menu = nc->global_data;
×
239
  menu_queue_redraw(menu, MENU_REDRAW_FULL);
×
240
  mutt_debug(LL_DEBUG5, "config done, request WA_RECALC, MENU_REDRAW_FULL\n");
×
241

242
  return 0;
×
243
}
244

245
/**
246
 * pattern_window_observer - Notification that a Window has changed - Implements ::observer_t - @ingroup observer_api
247
 *
248
 * This function is triggered by changes to the windows.
249
 *
250
 * - Delete (this window): clean up the resources held by the Help Bar
251
 */
252
static int pattern_window_observer(struct NotifyCallback *nc)
×
253
{
254
  if (nc->event_type != NT_WINDOW)
×
255
    return 0;
256
  if (!nc->global_data || !nc->event_data)
×
257
    return -1;
258
  if (nc->event_subtype != NT_WINDOW_DELETE)
×
259
    return 0;
260

261
  struct MuttWindow *win_menu = nc->global_data;
262
  struct EventWindow *ev_w = nc->event_data;
263
  if (ev_w->win != win_menu)
×
264
    return 0;
265

266
  struct Menu *menu = win_menu->wdata;
×
267

268
  notify_observer_remove(NeoMutt->sub->notify, pattern_config_observer, menu);
×
269
  notify_observer_remove(win_menu->notify, pattern_window_observer, win_menu);
×
270

271
  mutt_debug(LL_DEBUG5, "window delete done\n");
×
272
  return 0;
×
273
}
274

275
/**
276
 * dlg_pattern - Show menu to select a Pattern - @ingroup gui_dlg
277
 * @param buf Buffer for the selected Pattern
278
 * @retval true A selection was made
279
 *
280
 * The Select Pattern Dialog shows the user a help page of Patterns.
281
 * They can select one to auto-complete some functions, e.g. `<limit>`
282
 */
283
bool dlg_pattern(struct Buffer *buf)
×
284
{
285
  struct PatternData *pd = pattern_data_new();
×
286

287
  struct SimpleDialogWindows sdw = simple_dialog_new(MENU_GENERIC, WT_DLG_PATTERN, PatternHelp);
×
288
  create_pattern_entries(&pd->entries);
×
289

290
  struct Menu *menu = sdw.menu;
×
291
  pd->menu = menu;
×
292
  pd->buf = buf;
×
293

294
  menu->mdata = pd;
×
295
  menu->mdata_free = pattern_data_free;
×
296
  menu->make_entry = pattern_make_entry;
×
297
  menu->max = ARRAY_SIZE(&pd->entries);
×
298

299
  // L10N: Pattern completion menu title
300
  sbar_set_title(sdw.sbar, _("Patterns"));
×
301

302
  // NT_COLOR is handled by the SimpleDialog
303
  notify_observer_add(NeoMutt->sub->notify, NT_CONFIG, pattern_config_observer, menu);
×
304
  notify_observer_add(menu->win->notify, NT_WINDOW, pattern_window_observer, menu->win);
×
305

306
  struct MuttWindow *old_focus = window_set_focus(menu->win);
×
307
  // ---------------------------------------------------------------------------
308
  // Event Loop
309
  int op = OP_NULL;
310
  do
311
  {
312
    menu_tagging_dispatcher(menu->win, op);
×
313
    window_redraw(NULL);
×
314

315
    op = km_dokey(MENU_DIALOG, GETCH_NO_FLAGS);
×
316
    mutt_debug(LL_DEBUG1, "Got op %s (%d)\n", opcodes_get_name(op), op);
×
317
    if (op < 0)
×
318
      continue;
×
319
    if (op == OP_NULL)
×
320
    {
321
      km_error_key(MENU_GENERIC);
×
322
      continue;
×
323
    }
324
    mutt_clear_error();
×
325

326
    int rc = pattern_function_dispatcher(sdw.dlg, op);
×
327
    if (rc == FR_UNKNOWN)
×
328
      rc = menu_function_dispatcher(menu->win, op);
×
329
    if (rc == FR_UNKNOWN)
×
330
      rc = global_function_dispatcher(NULL, op);
×
331
  } while (!pd->done);
×
332
  // ---------------------------------------------------------------------------
333

334
  bool rc = pd->selection;
×
335

336
  window_set_focus(old_focus);
×
337
  simple_dialog_free(&sdw.dlg);
×
338

339
  return rc;
×
340
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc