NeoMutt  2025-09-05-55-g97fc89
Teaching an old dog new tricks
DOXYGEN
Loading...
Searching...
No Matches
expando.c
Go to the documentation of this file.
1
22
28
29#include "config.h"
30#include <grp.h>
31#include <pwd.h>
32#include <stdbool.h>
33#include <sys/stat.h>
34#include <time.h>
35#include "mutt/lib.h"
36#include "config/lib.h"
37#include "core/lib.h"
38#include "expando.h"
39#include "lib.h"
40#include "expando/lib.h"
41#include "muttlib.h"
42
46static void folder_date(const struct ExpandoNode *node, void *data,
47 MuttFormatFlags flags, struct Buffer *buf)
48{
49 const struct Folder *folder = data;
50 if (!folder->ff->local)
51 return;
52
53 static const time_t one_year = 31536000;
54 const char *t_fmt = ((mutt_date_now() - folder->ff->mtime) < one_year) ?
55 "%b %d %H:%M" :
56 "%b %d %Y";
57
58 char tmp[128] = { 0 };
59
60 mutt_date_localtime_format(tmp, sizeof(tmp), t_fmt, folder->ff->mtime);
61
62 buf_strcpy(buf, tmp);
63}
64
68static long folder_date_num(const struct ExpandoNode *node, void *data, MuttFormatFlags flags)
69{
70 const struct Folder *folder = data;
71 if (!folder->ff->local)
72 return 0;
73
74 return folder->ff->mtime;
75}
76
80static void folder_date_format(const struct ExpandoNode *node, void *data,
81 MuttFormatFlags flags, struct Buffer *buf)
82{
83 const struct Folder *folder = data;
84 if (!folder->ff->local)
85 return;
86
87 char tmp[128] = { 0 };
88 bool use_c_locale = false;
89 const char *const c_date_format = cs_subset_string(NeoMutt->sub, "date_format");
90 const char *t_fmt = NONULL(c_date_format);
91 if (*t_fmt == '!')
92 {
93 t_fmt++;
94 use_c_locale = true;
95 }
96
97 if (use_c_locale)
98 {
99 mutt_date_localtime_format_locale(tmp, sizeof(tmp), t_fmt,
100 folder->ff->mtime, NeoMutt->time_c_locale);
101 }
102 else
103 {
104 mutt_date_localtime_format(tmp, sizeof(tmp), t_fmt, folder->ff->mtime);
105 }
106
107 buf_strcpy(buf, tmp);
108}
109
113static long folder_date_format_num(const struct ExpandoNode *node, void *data, MuttFormatFlags flags)
114{
115 const struct Folder *folder = data;
116 if (!folder->ff->local)
117 return 0;
118
119 return folder->ff->mtime;
120}
121
125static void folder_date_strf(const struct ExpandoNode *node, void *data,
126 MuttFormatFlags flags, struct Buffer *buf)
127{
128 const struct Folder *folder = data;
129
130 if (!folder->ff->local)
131 return;
132
133 bool use_c_locale = false;
134 const char *text = node->text;
135 if (*text == '!')
136 {
137 use_c_locale = true;
138 text++;
139 }
140
141 char tmp[128] = { 0 };
142 struct tm tm = mutt_date_localtime(folder->ff->mtime);
143
144 if (use_c_locale)
145 {
146 strftime_l(tmp, sizeof(tmp), text, &tm, NeoMutt->time_c_locale);
147 }
148 else
149 {
150 strftime(tmp, sizeof(tmp), text, &tm);
151 }
152
153 buf_strcpy(buf, tmp);
154}
155
159static long folder_date_strf_num(const struct ExpandoNode *node, void *data, MuttFormatFlags flags)
160{
161 const struct Folder *folder = data;
162
163 if (!folder->ff->local)
164 return 0;
165
166 return folder->ff->mtime;
167}
168
172static void folder_description(const struct ExpandoNode *node, void *data,
173 MuttFormatFlags flags, struct Buffer *buf)
174{
175 const struct Folder *folder = data;
176
177 const char *s = NULL;
178 if (folder->ff->desc)
179 s = folder->ff->desc;
180 else
181 s = folder->ff->name;
182
183 buf_printf(buf, "%s%s", s,
184 folder->ff->local ?
185 (S_ISLNK(folder->ff->mode) ?
186 "@" :
187 (S_ISDIR(folder->ff->mode) ?
188 "/" :
189 (((folder->ff->mode & S_IXUSR) != 0) ? "*" : ""))) :
190 "");
191}
192
196static void folder_filename(const struct ExpandoNode *node, void *data,
197 MuttFormatFlags flags, struct Buffer *buf)
198{
199 const struct Folder *folder = data;
200
201 const char *s = NONULL(folder->ff->name);
202
203 buf_printf(buf, "%s%s", s,
204 folder->ff->local ?
205 (S_ISLNK(folder->ff->mode) ?
206 "@" :
207 (S_ISDIR(folder->ff->mode) ?
208 "/" :
209 (((folder->ff->mode & S_IXUSR) != 0) ? "*" : ""))) :
210 "");
211}
212
216static void folder_file_group(const struct ExpandoNode *node, void *data,
217 MuttFormatFlags flags, struct Buffer *buf)
218{
219 const struct Folder *folder = data;
220 if (!folder->ff->local)
221 return;
222
223 struct group *gr = getgrgid(folder->ff->gid);
224 if (gr)
225 {
226 buf_addstr(buf, gr->gr_name);
227 }
228 else
229 {
230 buf_printf(buf, "%u", folder->ff->gid);
231 }
232}
233
237static void folder_file_mode(const struct ExpandoNode *node, void *data,
238 MuttFormatFlags flags, struct Buffer *buf)
239{
240 const struct Folder *folder = data;
241
242 if (folder->ff->local)
243 {
244 buf_printf(buf, "%c%c%c%c%c%c%c%c%c%c",
245 S_ISDIR(folder->ff->mode) ? 'd' : (S_ISLNK(folder->ff->mode) ? 'l' : '-'),
246 ((folder->ff->mode & S_IRUSR) != 0) ? 'r' : '-',
247 ((folder->ff->mode & S_IWUSR) != 0) ? 'w' : '-',
248 ((folder->ff->mode & S_ISUID) != 0) ? 's' :
249 ((folder->ff->mode & S_IXUSR) != 0) ? 'x' :
250 '-',
251 ((folder->ff->mode & S_IRGRP) != 0) ? 'r' : '-',
252 ((folder->ff->mode & S_IWGRP) != 0) ? 'w' : '-',
253 ((folder->ff->mode & S_ISGID) != 0) ? 's' :
254 ((folder->ff->mode & S_IXGRP) != 0) ? 'x' :
255 '-',
256 ((folder->ff->mode & S_IROTH) != 0) ? 'r' : '-',
257 ((folder->ff->mode & S_IWOTH) != 0) ? 'w' : '-',
258 ((folder->ff->mode & S_ISVTX) != 0) ? 't' :
259 ((folder->ff->mode & S_IXOTH) != 0) ? 'x' :
260 '-');
261 }
262 else if (folder->ff->imap)
263 {
264 /* mark folders with subfolders AND mail */
265 buf_printf(buf, "IMAP %c", (folder->ff->inferiors && folder->ff->selectable) ? '+' : ' ');
266 }
267}
268
272static void folder_file_owner(const struct ExpandoNode *node, void *data,
273 MuttFormatFlags flags, struct Buffer *buf)
274{
275 const struct Folder *folder = data;
276 if (!folder->ff->local)
277 return;
278
279 struct passwd *pw = getpwuid(folder->ff->uid);
280 if (pw)
281 {
282 buf_addstr(buf, pw->pw_name);
283 }
284 else
285 {
286 buf_printf(buf, "%u", folder->ff->uid);
287 }
288}
289
293static void folder_file_size(const struct ExpandoNode *node, void *data,
294 MuttFormatFlags flags, struct Buffer *buf)
295{
296 const struct Folder *folder = data;
297
298 mutt_str_pretty_size(buf, folder->ff->size);
299}
300
304static long folder_file_size_num(const struct ExpandoNode *node, void *data, MuttFormatFlags flags)
305{
306 const struct Folder *folder = data;
307 return folder->ff->size;
308}
309
313static void folder_hard_links(const struct ExpandoNode *node, void *data,
314 MuttFormatFlags flags, struct Buffer *buf)
315{
316 const struct Folder *folder = data;
317 if (!folder->ff->local)
318 return;
319
320 buf_add_printf(buf, "%d", (int) folder->ff->nlink);
321}
322
326static long folder_hard_links_num(const struct ExpandoNode *node, void *data, MuttFormatFlags flags)
327{
328 const struct Folder *folder = data;
329
330 if (folder->ff->local)
331 return folder->ff->nlink;
332
333 return 0;
334}
335
339static void folder_message_count(const struct ExpandoNode *node, void *data,
340 MuttFormatFlags flags, struct Buffer *buf)
341{
342 const struct Folder *folder = data;
343 if (!folder->ff->has_mailbox)
344 return;
345
346 buf_add_printf(buf, "%d", folder->ff->msg_count);
347}
348
352static long folder_message_count_num(const struct ExpandoNode *node, void *data,
353 MuttFormatFlags flags)
354{
355 const struct Folder *folder = data;
356
357 if (folder->ff->has_mailbox)
358 return folder->ff->msg_count;
359
360 return 0;
361}
362
366static void folder_new_mail(const struct ExpandoNode *node, void *data,
367 MuttFormatFlags flags, struct Buffer *buf)
368{
369 const struct Folder *folder = data;
370
371 // NOTE(g0mb4): use $to_chars?
372 const char *s = folder->ff->has_new_mail ? "N" : " ";
373 buf_strcpy(buf, s);
374}
375
379static long folder_new_mail_num(const struct ExpandoNode *node, void *data, MuttFormatFlags flags)
380{
381 const struct Folder *folder = data;
382 return folder->ff->has_new_mail;
383}
384
388static long folder_notify_num(const struct ExpandoNode *node, void *data, MuttFormatFlags flags)
389{
390 const struct Folder *folder = data;
391
392 return folder->ff->notify_user;
393}
394
398static long folder_number_num(const struct ExpandoNode *node, void *data, MuttFormatFlags flags)
399{
400 const struct Folder *folder = data;
401
402 return folder->num + 1;
403}
404
408static long folder_poll_num(const struct ExpandoNode *node, void *data, MuttFormatFlags flags)
409{
410 const struct Folder *folder = data;
411
412 return folder->ff->poll_new_mail;
413}
414
418static void folder_tagged(const struct ExpandoNode *node, void *data,
419 MuttFormatFlags flags, struct Buffer *buf)
420{
421 const struct Folder *folder = data;
422
423 // NOTE(g0mb4): use $to_chars?
424 const char *s = folder->ff->tagged ? "*" : " ";
425 buf_strcpy(buf, s);
426}
427
431static long folder_tagged_num(const struct ExpandoNode *node, void *data, MuttFormatFlags flags)
432{
433 const struct Folder *folder = data;
434 return folder->ff->tagged;
435}
436
440static void folder_unread_count(const struct ExpandoNode *node, void *data,
441 MuttFormatFlags flags, struct Buffer *buf)
442{
443 const struct Folder *folder = data;
444 if (!folder->ff->has_mailbox)
445 return;
446
447 buf_add_printf(buf, "%d", folder->ff->msg_unread);
448}
449
453static long folder_unread_count_num(const struct ExpandoNode *node, void *data,
454 MuttFormatFlags flags)
455{
456 const struct Folder *folder = data;
457
458 if (folder->ff->has_mailbox)
459 return folder->ff->msg_unread;
460
461 return 0;
462}
463
467static void global_padding_space(const struct ExpandoNode *node, void *data,
468 MuttFormatFlags flags, struct Buffer *buf)
469{
470 buf_addstr(buf, " ");
471}
472
const struct ExpandoRenderCallback FolderRenderCallbacks[]
Callbacks for Browser Expandos.
Definition expando.c:478
Browser Expando definitions.
Select a Mailbox from a list.
@ 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:159
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:352
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:304
static long folder_hard_links_num(const struct ExpandoNode *node, void *data, MuttFormatFlags flags)
Browser: Hard links - Implements get_number_t -.
Definition expando.c:326
static long folder_number_num(const struct ExpandoNode *node, void *data, MuttFormatFlags flags)
Browser: Index number - Implements get_number_t -.
Definition expando.c:398
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:379
static long folder_tagged_num(const struct ExpandoNode *node, void *data, MuttFormatFlags flags)
Browser: Is Tagged - Implements get_number_t -.
Definition expando.c:431
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:388
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:408
static long folder_date_num(const struct ExpandoNode *node, void *data, MuttFormatFlags flags)
Browser: Last modified - Implements get_number_t -.
Definition expando.c:68
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:453
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:113
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:366
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:418
static void folder_description(const struct ExpandoNode *node, void *data, MuttFormatFlags flags, struct Buffer *buf)
Browser: Description - Implements get_string_t -.
Definition expando.c:172
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:125
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:46
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:237
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:80
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:216
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:293
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:467
static void folder_filename(const struct ExpandoNode *node, void *data, MuttFormatFlags flags, struct Buffer *buf)
Browser: Filename - Implements get_string_t -.
Definition expando.c:196
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:313
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:272
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:339
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:440
struct tm mutt_date_localtime(time_t t)
Converts calendar time to a broken-down time structure expressed in user timezone.
Definition date.c:905
size_t mutt_date_localtime_format(char *buf, size_t buflen, const char *format, time_t t)
Format localtime.
Definition date.c:950
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:968
time_t mutt_date_now(void)
Return the number of seconds since the Unix epoch.
Definition date.c:455
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:989
Some miscellaneous functions.
uint8_t MuttFormatFlags
Flags for expando_render(), e.g. MUTT_FORMAT_FORCESUBJ.
Definition render.h:32
#define NONULL(x)
Definition string2.h:43
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
bool local
Folder is on local filesystem.
Definition lib.h:99
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