NeoMutt  2025-01-09-117-gace867
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
expando.c
Go to the documentation of this file.
1
29#include "config.h"
30#include <grp.h>
31#include <pwd.h>
32#include <stdbool.h>
33#include <stdio.h>
34#include <sys/stat.h>
35#include <time.h>
36#include "mutt/lib.h"
37#include "config/lib.h"
38#include "core/lib.h"
39#include "expando.h"
40#include "lib.h"
41#include "expando/lib.h"
42#include "muttlib.h"
43
47static void folder_date(const struct ExpandoNode *node, void *data,
48 MuttFormatFlags flags, struct Buffer *buf)
49{
50 const struct Folder *folder = data;
51 if (!folder->ff->local)
52 return;
53
54 static const time_t one_year = 31536000;
55 const char *t_fmt = ((mutt_date_now() - folder->ff->mtime) < one_year) ?
56 "%b %d %H:%M" :
57 "%b %d %Y";
58
59 char tmp[128] = { 0 };
60
61 mutt_date_localtime_format(tmp, sizeof(tmp), t_fmt, folder->ff->mtime);
62
63 buf_strcpy(buf, tmp);
64}
65
69static long folder_date_num(const struct ExpandoNode *node, void *data, MuttFormatFlags flags)
70{
71 const struct Folder *folder = data;
72 if (!folder->ff->local)
73 return 0;
74
75 return folder->ff->mtime;
76}
77
81static void folder_date_format(const struct ExpandoNode *node, void *data,
82 MuttFormatFlags flags, struct Buffer *buf)
83{
84 const struct Folder *folder = data;
85 if (!folder->ff->local)
86 return;
87
88 char tmp[128] = { 0 };
89 bool use_c_locale = false;
90 const char *const c_date_format = cs_subset_string(NeoMutt->sub, "date_format");
91 const char *t_fmt = NONULL(c_date_format);
92 if (*t_fmt == '!')
93 {
94 t_fmt++;
95 use_c_locale = true;
96 }
97
98 if (use_c_locale)
99 {
100 mutt_date_localtime_format_locale(tmp, sizeof(tmp), t_fmt,
101 folder->ff->mtime, NeoMutt->time_c_locale);
102 }
103 else
104 {
105 mutt_date_localtime_format(tmp, sizeof(tmp), t_fmt, folder->ff->mtime);
106 }
107
108 buf_strcpy(buf, tmp);
109}
110
114static long folder_date_format_num(const struct ExpandoNode *node, void *data, MuttFormatFlags flags)
115{
116 const struct Folder *folder = data;
117 if (!folder->ff->local)
118 return 0;
119
120 return folder->ff->mtime;
121}
122
126static void folder_date_strf(const struct ExpandoNode *node, void *data,
127 MuttFormatFlags flags, struct Buffer *buf)
128{
129 const struct Folder *folder = data;
130
131 if (!folder->ff->local)
132 return;
133
134 bool use_c_locale = false;
135 const char *text = node->text;
136 if (*text == '!')
137 {
138 use_c_locale = true;
139 text++;
140 }
141
142 char tmp[128] = { 0 };
143 struct tm tm = mutt_date_localtime(folder->ff->mtime);
144
145 if (use_c_locale)
146 {
147 strftime_l(tmp, sizeof(tmp), text, &tm, NeoMutt->time_c_locale);
148 }
149 else
150 {
151 strftime(tmp, sizeof(tmp), text, &tm);
152 }
153
154 buf_strcpy(buf, tmp);
155}
156
160static long folder_date_strf_num(const struct ExpandoNode *node, void *data, MuttFormatFlags flags)
161{
162 const struct Folder *folder = data;
163
164 if (!folder->ff->local)
165 return 0;
166
167 return folder->ff->mtime;
168}
169
173static void folder_description(const struct ExpandoNode *node, void *data,
174 MuttFormatFlags flags, struct Buffer *buf)
175{
176 const struct Folder *folder = data;
177
178 const char *s = NULL;
179 if (folder->ff->desc)
180 s = folder->ff->desc;
181 else
182 s = folder->ff->name;
183
184 buf_printf(buf, "%s%s", s,
185 folder->ff->local ?
186 (S_ISLNK(folder->ff->mode) ?
187 "@" :
188 (S_ISDIR(folder->ff->mode) ?
189 "/" :
190 (((folder->ff->mode & S_IXUSR) != 0) ? "*" : ""))) :
191 "");
192}
193
197static void folder_filename(const struct ExpandoNode *node, void *data,
198 MuttFormatFlags flags, struct Buffer *buf)
199{
200 const struct Folder *folder = data;
201
202 const char *s = NONULL(folder->ff->name);
203
204 buf_printf(buf, "%s%s", s,
205 folder->ff->local ?
206 (S_ISLNK(folder->ff->mode) ?
207 "@" :
208 (S_ISDIR(folder->ff->mode) ?
209 "/" :
210 (((folder->ff->mode & S_IXUSR) != 0) ? "*" : ""))) :
211 "");
212}
213
217static void folder_file_group(const struct ExpandoNode *node, void *data,
218 MuttFormatFlags flags, struct Buffer *buf)
219{
220 const struct Folder *folder = data;
221 if (!folder->ff->local)
222 return;
223
224 struct group *gr = getgrgid(folder->ff->gid);
225 if (gr)
226 {
227 buf_addstr(buf, gr->gr_name);
228 }
229 else
230 {
231 buf_printf(buf, "%u", folder->ff->gid);
232 }
233}
234
238static void folder_file_mode(const struct ExpandoNode *node, void *data,
239 MuttFormatFlags flags, struct Buffer *buf)
240{
241 const struct Folder *folder = data;
242
243 if (folder->ff->local)
244 {
245 buf_printf(buf, "%c%c%c%c%c%c%c%c%c%c",
246 S_ISDIR(folder->ff->mode) ? 'd' : (S_ISLNK(folder->ff->mode) ? 'l' : '-'),
247 ((folder->ff->mode & S_IRUSR) != 0) ? 'r' : '-',
248 ((folder->ff->mode & S_IWUSR) != 0) ? 'w' : '-',
249 ((folder->ff->mode & S_ISUID) != 0) ? 's' :
250 ((folder->ff->mode & S_IXUSR) != 0) ? 'x' :
251 '-',
252 ((folder->ff->mode & S_IRGRP) != 0) ? 'r' : '-',
253 ((folder->ff->mode & S_IWGRP) != 0) ? 'w' : '-',
254 ((folder->ff->mode & S_ISGID) != 0) ? 's' :
255 ((folder->ff->mode & S_IXGRP) != 0) ? 'x' :
256 '-',
257 ((folder->ff->mode & S_IROTH) != 0) ? 'r' : '-',
258 ((folder->ff->mode & S_IWOTH) != 0) ? 'w' : '-',
259 ((folder->ff->mode & S_ISVTX) != 0) ? 't' :
260 ((folder->ff->mode & S_IXOTH) != 0) ? 'x' :
261 '-');
262 }
263 else if (folder->ff->imap)
264 {
265 /* mark folders with subfolders AND mail */
266 buf_printf(buf, "IMAP %c", (folder->ff->inferiors && folder->ff->selectable) ? '+' : ' ');
267 }
268}
269
273static void folder_file_owner(const struct ExpandoNode *node, void *data,
274 MuttFormatFlags flags, struct Buffer *buf)
275{
276 const struct Folder *folder = data;
277 if (!folder->ff->local)
278 return;
279
280 struct passwd *pw = getpwuid(folder->ff->uid);
281 if (pw)
282 {
283 buf_addstr(buf, pw->pw_name);
284 }
285 else
286 {
287 buf_printf(buf, "%u", folder->ff->uid);
288 }
289}
290
294static void folder_file_size(const struct ExpandoNode *node, void *data,
295 MuttFormatFlags flags, struct Buffer *buf)
296{
297 const struct Folder *folder = data;
298
299 mutt_str_pretty_size(buf, folder->ff->size);
300}
301
305static long folder_file_size_num(const struct ExpandoNode *node, void *data, MuttFormatFlags flags)
306{
307 const struct Folder *folder = data;
308 return folder->ff->size;
309}
310
314static void folder_hard_links(const struct ExpandoNode *node, void *data,
315 MuttFormatFlags flags, struct Buffer *buf)
316{
317 const struct Folder *folder = data;
318 if (!folder->ff->local)
319 return;
320
321 buf_add_printf(buf, "%d", (int) folder->ff->nlink);
322}
323
327static long folder_hard_links_num(const struct ExpandoNode *node, void *data, MuttFormatFlags flags)
328{
329 const struct Folder *folder = data;
330
331 if (folder->ff->local)
332 return folder->ff->nlink;
333
334 return 0;
335}
336
340static void folder_message_count(const struct ExpandoNode *node, void *data,
341 MuttFormatFlags flags, struct Buffer *buf)
342{
343 const struct Folder *folder = data;
344 if (!folder->ff->has_mailbox)
345 return;
346
347 buf_add_printf(buf, "%d", folder->ff->msg_count);
348}
349
353static long folder_message_count_num(const struct ExpandoNode *node, void *data,
354 MuttFormatFlags flags)
355{
356 const struct Folder *folder = data;
357
358 if (folder->ff->has_mailbox)
359 return folder->ff->msg_count;
360
361 return 0;
362}
363
367static void folder_new_mail(const struct ExpandoNode *node, void *data,
368 MuttFormatFlags flags, struct Buffer *buf)
369{
370 const struct Folder *folder = data;
371
372 // NOTE(g0mb4): use $to_chars?
373 const char *s = folder->ff->has_new_mail ? "N" : " ";
374 buf_strcpy(buf, s);
375}
376
380static long folder_new_mail_num(const struct ExpandoNode *node, void *data, MuttFormatFlags flags)
381{
382 const struct Folder *folder = data;
383 return folder->ff->has_new_mail;
384}
385
389static long folder_notify_num(const struct ExpandoNode *node, void *data, MuttFormatFlags flags)
390{
391 const struct Folder *folder = data;
392
393 return folder->ff->notify_user;
394}
395
399static long folder_number_num(const struct ExpandoNode *node, void *data, MuttFormatFlags flags)
400{
401 const struct Folder *folder = data;
402
403 return folder->num + 1;
404}
405
409static long folder_poll_num(const struct ExpandoNode *node, void *data, MuttFormatFlags flags)
410{
411 const struct Folder *folder = data;
412
413 return folder->ff->poll_new_mail;
414}
415
419static void folder_tagged(const struct ExpandoNode *node, void *data,
420 MuttFormatFlags flags, struct Buffer *buf)
421{
422 const struct Folder *folder = data;
423
424 // NOTE(g0mb4): use $to_chars?
425 const char *s = folder->ff->tagged ? "*" : " ";
426 buf_strcpy(buf, s);
427}
428
432static long folder_tagged_num(const struct ExpandoNode *node, void *data, MuttFormatFlags flags)
433{
434 const struct Folder *folder = data;
435 return folder->ff->tagged;
436}
437
441static void folder_unread_count(const struct ExpandoNode *node, void *data,
442 MuttFormatFlags flags, struct Buffer *buf)
443{
444 const struct Folder *folder = data;
445 if (!folder->ff->has_mailbox)
446 return;
447
448 buf_add_printf(buf, "%d", folder->ff->msg_unread);
449}
450
454static long folder_unread_count_num(const struct ExpandoNode *node, void *data,
455 MuttFormatFlags flags)
456{
457 const struct Folder *folder = data;
458
459 if (folder->ff->has_mailbox)
460 return folder->ff->msg_unread;
461
462 return 0;
463}
464
468static void global_padding_space(const struct ExpandoNode *node, void *data,
469 MuttFormatFlags flags, struct Buffer *buf)
470{
471 buf_addstr(buf, " ");
472}
473
480 // clang-format off
499 { -1, -1, NULL, NULL },
500 // clang-format on
501};
const struct ExpandoRenderCallback FolderRenderCallbacks[]
Callbacks for Browser Expandos.
Definition: expando.c:479
@ ED_FOL_POLL
FolderFile.poll_new_mail.
Definition: lib.h:135
@ ED_FOL_NOTIFY
FolderFile.notify_user.
Definition: lib.h:133
@ ED_FOL_FILE_OWNER
FolderFile.uid.
Definition: lib.h:124
@ ED_FOL_FILE_GROUP
FolderFile.gid.
Definition: lib.h:122
@ ED_FOL_FILENAME
FolderFile.name.
Definition: lib.h:121
@ ED_FOL_DATE_FORMAT
FolderFile.mtime.
Definition: lib.h:118
@ ED_FOL_DATE_STRF
FolderFile.mtime.
Definition: lib.h:119
@ ED_FOL_UNREAD_COUNT
FolderFile.msg_unread.
Definition: lib.h:137
@ ED_FOL_FILE_MODE
FolderFile.move.
Definition: lib.h:123
@ ED_FOL_NEW_MAIL
FolderFile.has_new_mail.
Definition: lib.h:132
@ ED_FOL_FILE_SIZE
FolderFile.size.
Definition: lib.h:125
@ ED_FOL_HARD_LINKS
FolderFile.nlink.
Definition: lib.h:128
@ ED_FOL_DATE
FolderFile.mtime.
Definition: lib.h:117
@ ED_FOL_TAGGED
FolderFile.tagged.
Definition: lib.h:136
@ ED_FOL_NUMBER
Folder.num.
Definition: lib.h:134
@ ED_FOL_DESCRIPTION
FolderFile.desc, FolderFile.name.
Definition: lib.h:120
@ ED_FOL_MESSAGE_COUNT
FolderFile.msg_count.
Definition: lib.h:129
int buf_printf(struct Buffer *buf, const char *fmt,...)
Format a string overwriting a Buffer.
Definition: buffer.c:161
int buf_add_printf(struct Buffer *buf, const char *fmt,...)
Format a string appending a Buffer.
Definition: buffer.c:204
size_t buf_addstr(struct Buffer *buf, const char *s)
Add a string to a Buffer.
Definition: buffer.c:226
size_t buf_strcpy(struct Buffer *buf, const char *s)
Copy a string into a Buffer.
Definition: buffer.c:395
const char * cs_subset_string(const struct ConfigSubset *sub, const char *name)
Get a string config item by name.
Definition: helpers.c:291
Convenience wrapper for the config headers.
Convenience wrapper for the core headers.
@ ED_FOLDER
Folder ED_FOL_ ExpandoDataFolder.
Definition: domain.h:43
@ ED_GLOBAL
Global ED_GLO_ ExpandoDataGlobal.
Definition: domain.h:44
Parse Expando string.
static long folder_date_strf_num(const struct ExpandoNode *node, void *data, MuttFormatFlags flags)
Browser: Last modified (strftime) - Implements get_number_t -.
Definition: expando.c:160
static long folder_message_count_num(const struct ExpandoNode *node, void *data, MuttFormatFlags flags)
Browser: Number of messages - Implements get_number_t -.
Definition: expando.c:353
static long folder_file_size_num(const struct ExpandoNode *node, void *data, MuttFormatFlags flags)
Browser: Size in bytes - Implements get_number_t -.
Definition: expando.c:305
static long folder_hard_links_num(const struct ExpandoNode *node, void *data, MuttFormatFlags flags)
Browser: Hard links - Implements get_number_t -.
Definition: expando.c:327
static long folder_number_num(const struct ExpandoNode *node, void *data, MuttFormatFlags flags)
Browser: Index number - Implements get_number_t -.
Definition: expando.c:399
static long folder_new_mail_num(const struct ExpandoNode *node, void *data, MuttFormatFlags flags)
Browser: New mail flag - Implements get_number_t -.
Definition: expando.c:380
static long folder_tagged_num(const struct ExpandoNode *node, void *data, MuttFormatFlags flags)
Browser: Is Tagged - Implements get_number_t -.
Definition: expando.c:432
static long folder_notify_num(const struct ExpandoNode *node, void *data, MuttFormatFlags flags)
Browser: Alert for new mail - Implements get_number_t -.
Definition: expando.c:389
static long folder_poll_num(const struct ExpandoNode *node, void *data, MuttFormatFlags flags)
Browser: Poll for new mail - Implements get_number_t -.
Definition: expando.c:409
static long folder_date_num(const struct ExpandoNode *node, void *data, MuttFormatFlags flags)
Browser: Last modified - Implements get_number_t -.
Definition: expando.c:69
static long folder_unread_count_num(const struct ExpandoNode *node, void *data, MuttFormatFlags flags)
Browser: Number of unread messages - Implements get_number_t -.
Definition: expando.c:454
static long folder_date_format_num(const struct ExpandoNode *node, void *data, MuttFormatFlags flags)
Browser: Last modified ($date_format) - Implements get_number_t -.
Definition: expando.c:114
static void folder_new_mail(const struct ExpandoNode *node, void *data, MuttFormatFlags flags, struct Buffer *buf)
Browser: New mail flag - Implements get_string_t -.
Definition: expando.c:367
static void folder_tagged(const struct ExpandoNode *node, void *data, MuttFormatFlags flags, struct Buffer *buf)
Browser: Is Tagged - Implements get_string_t -.
Definition: expando.c:419
static void folder_description(const struct ExpandoNode *node, void *data, MuttFormatFlags flags, struct Buffer *buf)
Browser: Description - Implements get_string_t -.
Definition: expando.c:173
static void folder_date_strf(const struct ExpandoNode *node, void *data, MuttFormatFlags flags, struct Buffer *buf)
Browser: Last modified (strftime) - Implements get_string_t -.
Definition: expando.c:126
static void folder_date(const struct ExpandoNode *node, void *data, MuttFormatFlags flags, struct Buffer *buf)
Browser: Last modified - Implements get_string_t -.
Definition: expando.c:47
static void folder_file_mode(const struct ExpandoNode *node, void *data, MuttFormatFlags flags, struct Buffer *buf)
Browser: File permissions - Implements get_string_t -.
Definition: expando.c:238
static void folder_date_format(const struct ExpandoNode *node, void *data, MuttFormatFlags flags, struct Buffer *buf)
Browser: Last modified ($date_format) - Implements get_string_t -.
Definition: expando.c:81
static void folder_file_group(const struct ExpandoNode *node, void *data, MuttFormatFlags flags, struct Buffer *buf)
Browser: Group name - Implements get_string_t -.
Definition: expando.c:217
static void folder_file_size(const struct ExpandoNode *node, void *data, MuttFormatFlags flags, struct Buffer *buf)
Browser: Size in bytes - Implements get_string_t -.
Definition: expando.c:294
static void global_padding_space(const struct ExpandoNode *node, void *data, MuttFormatFlags flags, struct Buffer *buf)
Fixed whitespace - Implements get_string_t -.
Definition: expando.c:468
static void folder_filename(const struct ExpandoNode *node, void *data, MuttFormatFlags flags, struct Buffer *buf)
Browser: Filename - Implements get_string_t -.
Definition: expando.c:197
static void folder_hard_links(const struct ExpandoNode *node, void *data, MuttFormatFlags flags, struct Buffer *buf)
Browser: Hard links - Implements get_string_t -.
Definition: expando.c:314
static void folder_file_owner(const struct ExpandoNode *node, void *data, MuttFormatFlags flags, struct Buffer *buf)
Browser: Owner name - Implements get_string_t -.
Definition: expando.c:273
static void folder_message_count(const struct ExpandoNode *node, void *data, MuttFormatFlags flags, struct Buffer *buf)
Browser: Number of messages - Implements get_string_t -.
Definition: expando.c:340
static void folder_unread_count(const struct ExpandoNode *node, void *data, MuttFormatFlags flags, struct Buffer *buf)
Browser: Number of unread messages - Implements get_string_t -.
Definition: expando.c:441
struct tm mutt_date_localtime(time_t t)
Converts calendar time to a broken-down time structure expressed in user timezone.
Definition: date.c:906
size_t mutt_date_localtime_format(char *buf, size_t buflen, const char *format, time_t t)
Format localtime.
Definition: date.c:951
size_t mutt_date_localtime_format_locale(char *buf, size_t buflen, const char *format, time_t t, locale_t loc)
Format localtime using a given locale.
Definition: date.c:969
time_t mutt_date_now(void)
Return the number of seconds since the Unix epoch.
Definition: date.c:456
Convenience wrapper for the library headers.
int mutt_str_pretty_size(struct Buffer *buf, size_t num)
Display an abbreviated size, like 3.4K.
Definition: muttlib.c:1003
Some miscellaneous functions.
uint8_t MuttFormatFlags
Flags for expando_render(), e.g. MUTT_FORMAT_FORCESUBJ.
Definition: render.h:32
Sidebar Expando definitions.
Key value store.
#define NONULL(x)
Definition: string2.h:37
String manipulation buffer.
Definition: buffer.h:36
Basic Expando Node.
Definition: node.h:67
const char * text
Node-specific text.
Definition: node.h:73
bool selectable
Folder can be selected.
Definition: lib.h:96
bool imap
This is an IMAP folder.
Definition: lib.h:95
bool has_mailbox
This is a mailbox.
Definition: lib.h:98
char * name
Name of file/dir/mailbox.
Definition: lib.h:86
uid_t uid
File's User ID.
Definition: lib.h:82
bool tagged
Folder is tagged.
Definition: lib.h:102
gid_t gid
File's Group ID.
Definition: lib.h:83
bool has_new_mail
true if mailbox has "new mail"
Definition: lib.h:89
bool poll_new_mail
Check mailbox for new mail.
Definition: lib.h:101
bool notify_user
User will be notified of new mail.
Definition: lib.h:100
nlink_t nlink
Number of hard links.
Definition: lib.h:84
char * desc
Description of mailbox.
Definition: lib.h:87
off_t size
File size.
Definition: lib.h:80
time_t mtime
Modification time.
Definition: lib.h:81
int msg_count
total number of messages
Definition: lib.h:90
mode_t mode
File permissions.
Definition: lib.h:79
bool inferiors
Folder has children.
Definition: lib.h:97
int msg_unread
number of unread messages
Definition: lib.h:91
A folder/dir in the browser.
Definition: lib.h:69
int num
Number in the index.
Definition: lib.h:71
struct FolderFile * ff
File / Dir / Mailbox.
Definition: lib.h:70
Container for Accounts, Notifications.
Definition: neomutt.h:43
struct ConfigSubset * sub
Inherited config items.
Definition: neomutt.h:47
locale_t time_c_locale
Current locale but LC_TIME=C.
Definition: neomutt.h:49
@ ED_GLO_PADDING_SPACE
Space Padding.
Definition: uid.h:41