diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2018-01-19 14:36:10 +0200 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2018-01-19 14:47:58 +0200 |
commit | 5a7b63b21307c4271fd2d1ec57b706e56352da57 (patch) | |
tree | 0fa7dbda003dd86b8aea41330d4d36389736318a | |
parent | f74ed5e0a431cc70bba6832ef05c0615a1dc846d (diff) | |
download | mailutils-5a7b63b21307c4271fd2d1ec57b706e56352da57.tar.gz mailutils-5a7b63b21307c4271fd2d1ec57b706e56352da57.tar.bz2 |
Add new date/time specifier for headline variable in mail
The new %D specifier allows the user to supply arbitrary strftime(3)
format string for outputting message date/time. E.g.:
set headline="%4m %20D{%Y-%m-%dT%H:%M:%S} %18f %s"
* mail/from.c (hdr_date): Take format from data, if supplied.
(compile_headline): Handle the %D specifier
* mail/util.c (util_do_command): Return immediately if
command parsing failed.
* mail/tests/D.at: New testcase.
* mail/tests/Makefile.am: Add new testcase.
* mail/tests/testsuite.at: Likewise.
* NEWS: Document changes.
* doc/texinfo/strftime.texi: New file.
* doc/texinfo/Makefile.am: Add strftime.texi
* doc/texinfo/mailutils.texi: Include strftime.texi
* doc/texinfo/programs.texi: Document the %D format specifier.
-rw-r--r-- | NEWS | 20 | ||||
-rw-r--r-- | doc/texinfo/Makefile.am | 1 | ||||
-rw-r--r-- | doc/texinfo/mailutils.texi | 7 | ||||
-rw-r--r-- | doc/texinfo/programs.texi | 145 | ||||
-rw-r--r-- | doc/texinfo/strftime.texi | 155 | ||||
-rw-r--r-- | mail/from.c | 74 | ||||
-rw-r--r-- | mail/tests/D.at | 33 | ||||
-rw-r--r-- | mail/tests/Makefile.am | 1 | ||||
-rw-r--r-- | mail/tests/testsuite.at | 3 | ||||
-rw-r--r-- | mail/util.c | 7 |
10 files changed, 399 insertions, 47 deletions
@@ -1,9 +1,23 @@ -GNU mailutils NEWS -- history of user-visible changes. 2017-11-02 -Copyright (C) 2002-2017 Free Software Foundation, Inc. +GNU mailutils NEWS -- history of user-visible changes. 2018-01-19 +Copyright (C) 2002-2018 Free Software Foundation, Inc. See the end of file for copying conditions. Please send mailutils bug reports to <bug-mailutils@gnu.org>. +Git version + +* headline variable in the mail utility + +The new %D specifier has been implemented, which allows the user to +supply arbitrary strftime(3) format string for outputting message +date/time. E.g.: + + set headline="%4m %20D{%Y-%m-%dT%H:%M:%S} %18f %s" + +In simplified form, %D can be followed by a single time format +specifier. E.g. %DH can be used instead of %D{%H}. + + Version 3.4 - 2017-11-02 * Fix AM_MAILUTILS macro @@ -2076,7 +2090,7 @@ The first release. ---------------------------------------------------------------------- Copyright information: -Copyright (C) 2002-2017, Free Software Foundation, Inc. +Copyright (C) 2002-2018, Free Software Foundation, Inc. Permission is granted to anyone to make or distribute verbatim copies of this document as received, in any medium, provided that the diff --git a/doc/texinfo/Makefile.am b/doc/texinfo/Makefile.am index a22eac9cd..ed716a5c3 100644 --- a/doc/texinfo/Makefile.am +++ b/doc/texinfo/Makefile.am @@ -24,6 +24,7 @@ mailutils_TEXINFOS = \ mu-mh.texi\ programs.texi\ sieve.texi\ + strftime.texi\ usage.texi\ version.texi diff --git a/doc/texinfo/mailutils.texi b/doc/texinfo/mailutils.texi index fc9a7512d..eb287dd3d 100644 --- a/doc/texinfo/mailutils.texi +++ b/doc/texinfo/mailutils.texi @@ -50,7 +50,7 @@ Published by the Free Software Foundation, 51 Franklin Street, Fifth Floor Boston, MA 02110-1301, USA -Copyright @copyright{} 1999-2004, 2008-2012, 2014-2017 Free Software +Copyright @copyright{} 1999-2004, 2008-2012, 2014-2018 Free Software Foundation, Inc. Permission is granted to copy, distribute and/or modify this document @@ -99,6 +99,7 @@ Appendices * References:: References. * Date Input Formats:: +* Date/time Format String:: * Usage Vars:: Configuring Help Summary * GNU FDL:: This manual is under the GNU Free Documentation License. @@ -963,6 +964,10 @@ Wojciech Polak @email{polak@@gnu.org} @appendix Date Input Formats @include getdate.texi +@node Date/time Format String +@appendix Date/time Format String +@include strftime.texi + @node Usage Vars @appendix Configuring Help Summary @include usage.texi diff --git a/doc/texinfo/programs.texi b/doc/texinfo/programs.texi index 9bcd6c363..75632a3ba 100644 --- a/doc/texinfo/programs.texi +++ b/doc/texinfo/programs.texi @@ -1,5 +1,5 @@ @c This is part of the GNU Mailutils manual. -@c Copyright (C) 1999-2012, 2014-2017 Free Software Foundation, Inc. +@c Copyright (C) 1999-2012, 2014-2018 Free Software Foundation, Inc. @c See file mailutils.texi for copying conditions. @comment ******************************************************************* @@ -4972,55 +4972,140 @@ Unsetting this variable tells @command{mail} to obtain it from the Whether to run @code{headers} command automatically after entering interactive mode. +@anchor{headline} @kwindex headline @item headline @*Type: String @*Default: @samp{%>%a%4m %18f %16d %3l/%-5o %s} -A format string to use for the header summary. The @samp{%} character -introduces a @dfn{format specifier}. Valid format specifiers are: - -@multitable @columnfractions 0.2 0.8 -@headitem Letter @tab Meaning -@item %a @tab Message attributes. -@item %d @tab The date when the message was received. -@item %f @tab The address of the message sender. -@item %l @tab The number of lines of the message. -@item %m @tab Message number. -@item %o @tab The number of octets (bytes) in the message. -@item %s @tab Message subject (if any). -@item %S @tab Message subject (if any) in double quotes. -@item %> @tab A @samp{>} for the current message, otherwise a space. -@item %< @tab A @samp{<} for the current message, otherwise a space. -@item %% @tab A `%' character. -@end multitable +Format string to use for the header summary. The @samp{%} character +introduces a @dfn{format specifier}. The format specifier consists of +optional alignment specifier (@samp{+} or @samp{-} sign), optional +output width and the specifier letter. Format specifiers are replaced on +output with the corresponding piece of information from the message +being described. -Some additional symbols are allowed between @samp{%} and the specifier -letter. The @samp{-} character immediately following @samp{%} -indicates that this field should be left aligned. Similarly, the -@samp{+} character indicates right alignment. Default alignment -depends on the type of the specifier: the specifiers that produce -numeric values (@samp{%l}, @samp{%m}, and @samp{%o}) are aligned to -the right, whereas the ones producing string values are aligned to the -left. +The @samp{-} character immediately following @samp{%} indicates that +this field should be left aligned. The @samp{+} character indicates +right alignment. Default alignment depends on the type of the +specifier: the specifiers that produce numeric values (@samp{%l}, +@samp{%m}, and @samp{%o}) are aligned to the right, whereas the ones +producing string or date/time values are aligned to the left. A number following @samp{%} or the alignment flag, indicates the -field width. Consider, for example, the following specifiers: +field width. + +Consider the @samp{%m} specifier as an example: @table @asis @item %m Print current message number. Take as much screen columns as necessary -to output it. +for output. @item %4m @itemx %+4m -Print current message number. Occupy 4 screen columns, truncate the -output if it does not fit that width. Align the output to the right. +Print current message number. Use exactly 4 screen columns, +truncating the output if it does not fit that width. Align the output +to the right. @item %-4m Same as above, but align to the left. @end table +Valid format specifiers are: + +@table @asis +@item %a +Message attribute. One of the following letters, or a single +horizontal space, if none of them applies: + +@multitable @columnfractions 0.2 0.6 +@item @samp{M} @tab the message was copied to the mailbox (@samp{mbox} command) +@item @samp{P} @tab the message was preserved (@samp{hold} command) +@item @samp{*} @tab the message was saved (@samp{save} or @samp{Save}) +@item @samp{T} @tab the message was tagged (@samp{tag}) +@item @samp{R} @tab the message was read +@item @samp{N} @tab the message is new (was not seen) +@item @samp{U} @tab the message was seen, but wasn't read +@end multitable + +@item %d +The date when the message was received. It is determined from the +message header set by the @samp{datefield} variable +(@pxref{datefield}). If that variable is not set, or the requested +header is not present in the message, the date from the envelope is +used. + +The output is formatted according to the following format +specification (@pxref{Date/time Format String}): + +@example +%a %b %e %H:%M +@end example + +I.e.: abbreviated weekday name, abbreviated month name, day of the +month as a decimal number, followed by hour and minutes. All names +are displayed according to the current locale. + +@item %D@{@var{fmt}@} +Same as @samp{%d}, but the date is formatted according to the +date/time format @var{fmt}. It is essentially a C @samp{strftime} +format string, described in detail in @ref{Date/time Format String}. + +For example: + +@example +set headline="%4m %20D@{%Y-%m-%dT%H:%M:%S@}" +@end example + +Note, that the opening @samp{@{} must follow the format letter without +any intervening whitespace. If @var{fmt} contains @samp{@{}, +@samp{@}}, or @samp{\}, these characters must be escaped with +backslash (e.g. @samp{\@{}). + +@item %D@var{f} +A simplified form of the @samp{%D} specifier. It is equivalent to + +@example +%D@{%@var{f}@} +@end example + +@noindent +where @var{f} is a single @samp{strftime} specifier letter. It can be +preceded by @samp{E} or @samp{O}, if the Single UNIX Specification +allows such usage (@pxref{conversion specs}), e.g. @samp{%DOU}. + +Notice, that @samp{%D} not followed by a valid time format in either +of the above forms is treated as unknown specifier. + +@item %f +The email address of the message sender. + +@item %l +The number of lines of the message. + +@item %m +Message number. + +@item %o +The number of octets (bytes) in the message. + +@item %s +Message subject (if any). + +@item %S +Message subject (if any) in double quotes. + +@item %> +A @samp{>} for the current message, otherwise a space. + +@item %< +A @samp{<} for the current message, otherwise a space. + +@item %% +A @samp{%} character. +@end table + @kwindex hold @item hold @*Type: Boolean. diff --git a/doc/texinfo/strftime.texi b/doc/texinfo/strftime.texi new file mode 100644 index 000000000..a5f1c553c --- /dev/null +++ b/doc/texinfo/strftime.texi @@ -0,0 +1,155 @@ +@c This is part of the GNU Mailutils manual. +@c Copyright (C) 2018 Free Software Foundation, Inc. +@c See file mailutils.texi for copying conditions. +@c ******************************************************************* + +@cindex time formats, output + This appendix documents the format specifications for +outputting date/time values. It is used, in particular, by +the @command{mail} utility (@pxref{headline}). + +Essentially, it is a reproduction of the man page for GNU +@code{strftime} function. Some of the conversion specifiers might not +be available on all systems, due to differences in @samp{strftime} +between systems. If unsure, please consult +@ref{strftime, strftime,,strftime(3), the strftime(3) man page}. + + Ordinary characters placed in the format string are reproduced without +conversion. Conversion specifiers are introduced by a @samp{%} +character, and are replaced as follows: + +@multitable @columnfractions 0.2 0.7 +@item %a @tab The abbreviated weekday name according to the current locale. + +@item %A @tab The full weekday name according to the current locale. + +@item %b @tab The abbreviated month name according to the current locale. + +@item %B @tab The full month name according to the current locale. + +@anchor{%c time format} +@item %c @tab The preferred date and time representation for the current locale. + +@item %C @tab The century number (year/100) as a 2-digit integer. + +@item %d @tab The day of the month as a decimal number (range 01 to 31). + +@item %D @tab Equivalent to @samp{%m/%d/%y}. + +@item %e @tab Like @samp{%d}, the day of the month as a decimal +number, but a leading zero is replaced by a space. + +@item %E @tab Modifier: use alternative format, see below +(@pxref{conversion specs}). + +@item %F @tab Equivalent to @samp{%Y-%m-%d} (the ISO 8601 date format). + +@item %G +@tab The ISO 8601 year with century as a decimal number. +The 4-digit year corresponding to the ISO week number (see @samp{%V}). This +has the same format and value as @samp{%y}, except that if the ISO week +number belongs to the previous or next year, that year is used instead. + +@item %g @tab Like @samp{%G}, but without century, i.e., with a 2-digit + year (00-99). + +@item %h @tab Equivalent to @samp{%b}. + +@item %H @tab The hour as a decimal number using a 24-hour clock +(range 00 to 23). + +@item %I @tab The hour as a decimal number using a 12-hour clock +(range 01 to 12). + +@item %j @tab The day of the year as a decimal number (range 001 +to 366). + +@item %k @tab The hour (24-hour clock) as a decimal number (range +0 to 23); single digits are preceded by a blank. +(See also @samp{%H}.) + +@item %l @tab The hour (12-hour clock) as a decimal number (range +1 to 12); single digits are preceded by a blank. (See also @samp{%I}.) + +@item %m @tab The month as a decimal number (range 01 to 12). + +@item %M @tab The minute as a decimal number (range 00 to 59). + +@item %n @tab A newline character. + +@item %O @tab Modifier: use alternative format, see below +(@pxref{conversion specs}). + +@item %p @tab Either @samp{AM} or @samp{PM} according to the given time +value, or the corresponding strings for the current locale. Noon is +treated as @samp{pm} and midnight as @samp{am}. + +@item %P @tab Like @samp{%p} but in lowercase: @samp{am} or @samp{pm} +or a corresponding string for the current locale. + +@item %r @tab The time in @samp{a.m.} or @samp{p.m.} notation. In the POSIX +locale this is equivalent to @samp{%I:%M:%S %p}. + +@item %R @tab The time in 24-hour notation (@samp{%H:%M}). For a +version including the seconds, see @samp{%T} below. + +@anchor{%s time format} +@item %s @tab The number of seconds since the Epoch, i.e., since 1970-01-01 00:00:00 UTC. + +@item %S @tab The second as a decimal number (range 00 to 61). + +@item %t @tab A tab character. + +@item %T @tab The time in 24-hour notation (@samp{%H:%M:%S}). + +@item %u @tab The day of the week as a decimal, range 1 to 7, +Monday being 1. See also @samp{%w}. + +@item %U @tab The week number of the current year as a decimal number, +range 00 to 53, starting with the first Sunday as the first day of +week 01. See also @samp{%V} and @samp{%W}. + +@item %V @tab The ISO 8601:1988 week number of the current year +as a decimal number, range 01 to 53, where week 1 is the first week +that has at least 4 days in the current year, and with Monday as the +first day of the week. See also @samp{%U} and @samp{%W}. + +@item %w @tab The day of the week as a decimal, range 0 to 6, Sunday +being 0. See also @samp{%u}. + +@item %W @tab The week number of the current year as a decimal number, +range 00 to 53, starting with the first Monday as the first day of week 01. + +@item %x @tab The preferred date representation for the current locale +without the time. + +@item %X @tab The preferred time representation for the current locale +without the date. + +@item %y @tab The year as a decimal number without a century (range 00 to 99). + +@item %Y @tab The year as a decimal number including the century. + +@item %z @tab The time-zone as hour offset from @acronym{GMT}. Required to +emit RFC822-conformant dates (using @samp{%a, %d %b %Y %H:%M:%S %z}) + +@item %Z @tab The time zone or name or abbreviation. + +@item %+ @tab The date and time in @cite{date(1)} format. + +@item %% @tab A literal @samp{%} character. +@end multitable + +@anchor{conversion specs} +Some conversion specifiers can be modified by preceding them by the +@samp{E} or @samp{O} modifier to indicate that an alternative format +should be used. If the alternative format or specification does not +exist for the current locale, the behaviour will be as if the +unmodified conversion specification were used. The Single Unix +Specification mentions @samp{%Ec}, @samp{%EC}, @samp{%Ex}, @samp{%EX}, +@samp{%Ry}, @samp{%EY}, @samp{%Od}, @samp{%Oe}, @samp{%OH}, +@samp{%OI}, @samp{%Om}, @samp{%OM}, @samp{%OS}, @samp{%Ou}, +@samp{%OU}, @samp{%OV}, @samp{%Ow}, @samp{%OW}, @samp{%Oy}, where the +effect of the @samp{O} modifier is to use alternative numeric symbols +(say, roman numerals), and that of the @samp{E} modifier is to use a +locale-dependent alternative representation. diff --git a/mail/from.c b/mail/from.c index 1a99a0a4c..1ba408e4d 100644 --- a/mail/from.c +++ b/mail/from.c @@ -1,5 +1,5 @@ /* GNU Mailutils -- a suite of utilities for electronic mail - Copyright (C) 1999-2003, 2005, 2007, 2009-2012, 2014-2017 Free + Copyright (C) 1999-2003, 2005, 2007, 2009-2012, 2014-2018 Free Software Foundation, Inc. GNU Mailutils is free software; you can redistribute it and/or modify @@ -182,14 +182,15 @@ hdr_attr (struct header_call_args *args, void *data) cflag = ' '; return header_buf_string_len (args, &cflag, 1); } - -/* %d */ + +/* %d and %D*/ static char * hdr_date (struct header_call_args *args, void *data) { char date[80]; mu_header_t hdr; - + char const *fmt = data ? data : "%a %b %e %H:%M"; + mu_message_get_header (args->msg, &hdr); date[0] = 0; @@ -199,7 +200,7 @@ hdr_date (struct header_call_args *args, void *data) { time_t t; if (mu_parse_date (date, &t, NULL) == 0) - strftime (date, sizeof(date), "%a %b %e %H:%M", localtime (&t)); + strftime (date, sizeof(date), fmt, localtime (&t)); else date[0] = 0; } @@ -214,7 +215,7 @@ hdr_date (struct header_call_args *args, void *data) mu_message_get_envelope (args->msg, &env); if (mu_envelope_sget_date (env, &p) == 0 && mu_scan_datetime (p, MU_DATETIME_FROM, &tm, &tz, NULL) == 0) - strftime (date, sizeof(date), "%a %b %e %H:%M", &tm); + strftime (date, sizeof(date), fmt, &tm); } return header_buf_string (args, date); } @@ -467,10 +468,10 @@ compile_headline (const char *str) /* FIXME: %c The score of the message. */ - case 'd': /* Message date */ + case 'd': /* Message date; See also 'D', below. */ seg = new_header_segment (ALIGN_STRING, width, NULL, hdr_date); break; - + /* FIXME: %e The indenting level in threaded mode. */ case 'f': /* Message sender */ @@ -516,8 +517,63 @@ compile_headline (const char *str) hdr_cur); break; + case 'D': + { + int i; + /* strftime conversion specifiers */ + static char timespec[] = + "aAbBcCdDeFGghHIjklmMnpPrRsStTuUVwWxXyYzZ+%"; + /* Specifiers that can follow the E modifier */ + static char espec[] = + "cCxXyY"; + /* Specifiers that can follow the O modifier */ + static char ospec[] = + "deHImMSuUVwWy"; + + if (*str == '{') + { + for (i = 1; str[i] && str[i] != '}'; i++) + if (str[i] == '\\') + i++; + if (str[i]) + { + text = mu_alloc (i); + memcpy (text, str + 1, i - 1); + text[i - 1] = 0; + mu_c_str_unescape_inplace (text, "\\{}", NULL); + seg = new_header_segment (ALIGN_STRING, width, text, + hdr_date); + str += i + 1; + break; + } + } + else if (str[1] && + ((*str == 'E' && strchr (espec, str[1])) + || (*str == 'O' && strchr (ospec, str[1])))) + { + text = mu_alloc (4); + text[0] = '%'; + text[1] = *str++; + text[2] = *str++; + text[3] = 0; + seg = new_header_segment (ALIGN_STRING, width, text, + hdr_date); + break; + } + else if (strchr (timespec, *str)) + { + text = mu_alloc (3); + text[0] = '%'; + text[1] = *str++; + text[2] = 0; + seg = new_header_segment (ALIGN_STRING, width, text, + hdr_date); + break; + } + } + default: - mu_error (_("unknown escape: %%%c"), str[-1]); + mu_error (_("unknown format specifier: %%%c"), str[-1]); len = str - p; text = mu_alloc (len); memcpy (text, p, len-1); diff --git a/mail/tests/D.at b/mail/tests/D.at new file mode 100644 index 000000000..ffe78cb0b --- /dev/null +++ b/mail/tests/D.at @@ -0,0 +1,33 @@ +# This file is part of GNU Mailutils. -*- Autotest -*- +# Copyright (C) 2018 Free Software Foundation, Inc. +# +# GNU Mailutils is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License as +# published by the Free Software Foundation; either version 3, or (at +# your option) any later version. +# +# GNU Mailutils is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. + +# Test the %D headline specifier + +AT_SETUP([date formats]) +AT_KEYWORDS([date format]) + +AT_CHECK([ +MUT_MBCOPY($abs_top_srcdir/testsuite/spool/mbox) +MUT_MAIL_CMD --exec='set headline=">%d<"' --headers -f ./mbox +MUT_MAIL_CMD --exec='set headline=">%DH<"' --headers -f ./mbox +MUT_MAIL_CMD --exec='set headline=">%D{%Y-%m-%d \{%H:%M:%S\}}<"' --headers -f ./mbox +], +[0], +[>Tue Jul 16 12:11< +>12< +>2002-07-16 {12:11:35}< +]) +AT_CLEANUP
\ No newline at end of file diff --git a/mail/tests/Makefile.am b/mail/tests/Makefile.am index e6039ce4e..eaf899f22 100644 --- a/mail/tests/Makefile.am +++ b/mail/tests/Makefile.am @@ -39,6 +39,7 @@ $(srcdir)/package.m4: $(top_srcdir)/configure.ac ## ------------ ## TESTSUITE_AT =\ + D.at\ align.at\ cols00.at\ cols01.at\ diff --git a/mail/tests/testsuite.at b/mail/tests/testsuite.at index b8dee8e09..415adc3a5 100644 --- a/mail/tests/testsuite.at +++ b/mail/tests/testsuite.at @@ -30,4 +30,5 @@ m4_include([copy01.at]) m4_include([copy02.at]) m4_include([copy03.at]) m4_include([copy04.at]) -m4_include([align.at])
\ No newline at end of file +m4_include([align.at]) +m4_include([D.at])
\ No newline at end of file diff --git a/mail/util.c b/mail/util.c index e1399027a..b5f361be1 100644 --- a/mail/util.c +++ b/mail/util.c @@ -76,8 +76,9 @@ util_do_command (const char *fmt, ...) for expansion (see below) */ if (mu_wordsplit (cmd, &ws, MU_WRDSF_DEFFLAGS|MU_WRDSF_DOOFFS)) { - mu_error (_("%s failed: %s"), "mu_wordsplit", - mu_wordsplit_strerror (&ws)); + mu_error ("\"%s\": %s", cmd, mu_wordsplit_strerror (&ws)); + free (cmd); + return MU_ERR_PARSE; } else { @@ -98,8 +99,8 @@ util_do_command (const char *fmt, ...) } entry = mail_find_command (argv[0]); + free (cmd); } - free (cmd); } else entry = mail_find_command ("quit"); |