mutt:“ date_format”中的条件日期格式


15

index_format在mutt中设定了以下值:

"%Z %{%Y %b %e  %H:%M} %?X?(%X)&   ? %-22.22F  %.100s %> %5c "

它以以下格式显示日期

2013 Dec 5

我想知道是否有可能根据电子邮件的年龄而使用不同的日期格式。我的意思是:

for less than 7 days:  today, yesterday, tuesday, monday
this year:             Dec 5
older than this year:  2013 Dec 5

我想我已经在Thunderbird中看到了此功能。把它放在杂物中会很好

Answers:


16

如果您使用的是mutt(v1.5 +)的“开发”版本-绝对应该-使用该手册中所述的外部过滤器。

首先,您需要一个脚本,该脚本可以根据消息的使用期限输出不同的内容。这是Python中的示例:

#!/usr/bin/env python
"""mutt format date

Prints different index_format strings for mutt according to a
messages age.

The single command line argument should be a unix timestamp
giving the message's date (%{}, etc. in Mutt).
"""

import sys
from datetime import datetime

INDEX_FORMAT = "%Z {} %?X?(%X)&   ? %-22.22F  %.100s %> %5c%"

def age_fmt(msg_date, now):
    # use iso date for messages of the previous year and before
    if msg_date.date().year < now.date().year:
        return '%[%Y-%m-%d]'

    # use "Month Day" for messages of this year
    if msg_date.date() < now.date():
        return '%10[%b %e]'

    # if a message appears to come from the future
    if msg_date > now:
        return '  b0rken'

    # use only the time for messages that arrived today
    return '%10[%H:%m]'

if __name__ == '__main__':
    msg_date = datetime.fromtimestamp(int(sys.argv[1]))
    now = datetime.now()
    print INDEX_FORMAT.format(age_fmt(msg_date, now))

将此保存为mutt-fmt-datePATH上的某个位置。

这里有两点很重要:

  • 格式字符串必须包含一次{}age_fmt()用Python 的返回值代替。
  • 格式字符串必须以a结尾,%这样Mutt才能对其进行解释。

然后,您可以.muttrc按以下方式使用它:

set index_format="mutt-fmt-date %[%s] |"

然后笨蛋会

  1. %[%s]根据格式字符串的规则进行解释。
  2. 调用mutt-fmt-date与1作为参数(因为结果|在最后)。
  3. 再次将其从脚本中返回的内容解释为格式字符串(由于%末尾为)。

警告:将对将要显示的每条消息执行脚本。在邮箱中滚动时,产生的延迟可能非常明显。

这是C的版本,在某种程度上可以正常运行:

#include <stdlib.h>
#include <stdio.h>
#include <time.h>

#define DAY (time_t)86400
#define YEAR (time_t)31556926

int main(int argc, const char *argv[]) {
    time_t current_time;
    time_t message_time;

    const char *old, *recent, *today;
    const char *format;

    current_time = time(NULL);

    if (argc!=6) {
        printf("Usage: %s old recent today format timestamp\n", argv[0]);
        return 2;
    }

    old = argv[1];
    recent = argv[2];
    today = argv[3];

    format = argv[4];

    message_time = atoi(argv[5]);

    if ((message_time/YEAR) < (current_time/YEAR)) {
        printf(format, old);
    } else if ((message_time/DAY) < (current_time/DAY)) {
        printf(format, recent);
    } else {
        printf(format, today);
    }

    return 0;
}

这与muttrc行一起使用:

set index_format='mfdate "%[%d.%m.%y]" "%8[%e. %b]" "%8[%H:%m]" "%Z %%s %-20.20L %?y?[%-5.5y]&       ? %?M?+& ?%s%%" "%[%s]" |'

我还没有时间调试它,但是此解决方案和包含%符号的主题似乎存在问题。补丁将不胜感激!

1
我创造了赏金。您是否有解决此错误的想法?
Martin Vegter '17

7

不幸的是,当前的Mutt版本似乎无法做到这一点。

$index_format支持从各种消息元数据中提取的一组特定的格式说明符。它在Mutt手册中进行了描述(或相同的“稳定”版本的文档),并且从表中可以看到,只有少数格式说明符是有条件的。这些都是%M%y%Y; %M是隐藏的消息的数量,如果该线程处于折叠状态,和%y和%Y是X标签标头如果存在。

消息日期和时间的实际格式由来完成strftime(3),它根本不支持条件格式。

也许可以做一个丑陋通过不断改写消息文件解决办法Date:头,但我不想这样做,至少。但是,这是我能想到的最坏的可能性。

我能想到的唯一真正的解决方案是在Mutt中实现这种支持(几乎可以肯定是Thunderbird的方式),或者编写一个替换文件strftime来支持条件格式并使用LD_PRELOAD或类似机制来注入。但是,后者将影响通过strftime的Mutt中的所有日期和时间显示,不仅与消息索引有关。


2
如果您使用的是1.5+版本(绝对应该使用),则有一种方法。建议改写日期标题虽然很有趣……

@hop FWIW,您的回答得到了我的认可。
2014年

4

由于某种原因,较新版本的mutt(1.7出现了此问题)在日期字符串前加上了字符“ 14”和“ 32”,这使atoi不能将字符串转换为int。将行更改为

message_time = atoi(2+argv[7]);

可能是一个愚蠢的解决方案,但对我有用。


4

编辑了@Marcus的c版本(尽管仍然无法解决%主题问题):

// -*- coding:utf-8-unix; mode:c; -*-
/*
    Sets mutt index date based on mail age.

build:
    gcc mutt-index-date-formatter.c -o mutt-index-format
use this line in .muttrc:
    set index_format = 'mutt-index-format "%9[%d.%m.%y]" "%9[%e.%b]" "%8[%a %H:%m]" "%[%H:%m]" "%3C [%Z] %?X?%2X& -? %%s %-20.20L %?M?+%-2M&   ? %s %> [%4c]asladfg" "%[%s]" |'*/
// ////////////////////////////////////////////////////////////////

#include <stdlib.h>
#include <stdio.h>
#include <time.h>

#define DAY (time_t)86400
#define WEEK (time_t)604800
#define YEAR (time_t)31556926

int main(int argc, const char *argv[]) {
    time_t current_time;
    time_t message_time;
    struct tm *ltime;
    unsigned int todays_seconds=0;
    unsigned int seconds_this_morning=0;

    const char *last_year, *this_year, *last_months, *last_week, *today;
    const char *format;
    char *concat_str;

    current_time = time(NULL);
    ltime = localtime(&current_time);
    todays_seconds = ltime->tm_hour*3600 + ltime->tm_min*60 + ltime->tm_sec;
    seconds_this_morning = current_time - todays_seconds;  // unix time @ 00:00

    if (argc != 7) {
        printf("Usage: %s last_year this_year last_week today format timestamp\n", argv[0]);
        return 2;
    }

    last_year    = argv[1];
    this_year    = argv[2];
    last_week    = argv[3];
    today        = argv[4];

    format       = argv[5];

    message_time = atoi(2 + argv[6]);

    if (message_time >= seconds_this_morning) {
        asprintf(&concat_str, "    %s", today);
        printf(format, concat_str);
    } else if (message_time >= seconds_this_morning - DAY) {
        asprintf(&concat_str, "ydy %s", today);
        printf(format, concat_str);
    } else if (message_time > seconds_this_morning - WEEK) {
        printf(format, last_week);
    } else if (message_time/YEAR < current_time/YEAR) {
        printf(format, last_year);
    } else {
        printf(format, this_year);
    }

    return 0;
}

此格式的日期如下(所有时间均为24小时格式):

  • 02:04 今天的邮件
  • ydy 02:04 昨天的邮件
  • Thu 02:04 最近7天的邮件
  • 27.Mar 用于本年度的邮件
  • 13.12.16 前几年的邮件

本例中的完整索引格式为 #no [flags] #no_of_attachments date sender subject msg_size


3

进行了一些修改,但没有解决“主题百分比”问题

#include <stdlib.h>
#include <stdio.h>
#include <time.h>

#define DAY (time_t)86400
#define WEEK (time_t)604800
#define MONTH (time_t)2678400
#define YEAR (time_t)31556926

/*I use this line in .muttrc: 
 * set index_format        = '/home/marcus/.mutt/mfdate "%9[%d.%m.%y]" "%9[%e.%b]" " [%6[%e.%b]]" "%8[%a %H:%m]" "    %[%H:%m]" "%Z %%s %?X?%2X&  ? %-20.20L %?M?+%-2M&   ? %.86s %> [%4c]asladfg" "%[%s]" |'*/
int main(int argc, const char *argv[]) {
    time_t current_time;
    time_t message_time;
    struct tm *ltime;
    unsigned int todays_seconds=0;
    unsigned int seconds_this_morning=0;


    const char *last_year, *this_year, *last_months, *last_week, *today;
    const char *format;

    current_time = time(NULL);
    ltime = localtime(&current_time);
    todays_seconds = ltime->tm_hour*3600 + ltime->tm_min*60 + ltime->tm_sec;
    seconds_this_morning = current_time - todays_seconds;

    if (argc!=8) {
        printf("Usage: %s last_year this_year today format timestamp\n", argv[0]);
        return 2;
    }

    last_year    = argv[1];
    this_year    = argv[2];
    last_months  = argv[3];
    last_week    = argv[4];
    today        = argv[5];

    format       = argv[6];

    message_time = atoi(argv[7]);

    /*
     *if ((message_time+YEAR) < current_time) {
     *    printf(format, last_year);
     *} else if ((message_time+MONTH) < current_time) {
     *    printf(format, this_year);
     *} else if ((message_time+WEEK) < current_time) {
     *    printf(format, last_months);
     *} else if ((message_time+DAY) < current_time) {
     *    printf(format, last_week);
     *} else {
     *    printf(format, today);
     *}
     */

    if ((message_time/YEAR) < (current_time/YEAR)) {
        printf(format, last_year);
    } else if ((message_time/MONTH) < (current_time/MONTH)) {
        printf(format, this_year);
    } else if ((message_time + WEEK) < current_time) {
    /*} else if ((message_time/DAY) < (current_time/DAY)) {*/
        printf(format, last_months);
    /*
     *} else if ((message_time+DAY) < current_time) {
     *    printf(format, last_week);
     */
    } else if ((message_time ) < seconds_this_morning) {
        printf(format, last_week);
    } else {
        printf(format, today);
    }

    return 0;
}

如果您总结了所做的更改及其背后的原因,那将是很好的。
zagrimsan '16

0

这个index_format变量

set index_format='mfdate "%[%s]" "%4C %Z %[!%b %d %Y] %-17.17F (%3l) %s" |'

以及用户跳跃mfdate.c此答案中提出的修改:

#include <stdlib.h>
#include <stdio.h>
#include <time.h>

#define DAY (time_t)86400
#define YEAR (time_t)31556926

int main(int argc, const char *argv[]) {
  time_t current_time;
  time_t message_time;

  const char *old = "old";
  char *recent = "recent";
  char *today = "today";
  const char *format;

  current_time = time(NULL);

  if (argc != 3) {
    printf("Usage: %s format\n", argv[0]);
    return EXIT_FAILURE;
  }

  format = argv[2];

  message_time = atoi(argv[1]);

  if ((message_time/YEAR) < (current_time/YEAR)) {
    printf("%s,%s", old, format);
  } else if ((message_time/DAY) < (current_time/DAY)) {
    printf("%s,%s", recent, format);
  } else {
    printf("%s,%s", today, format);
  }

  return EXIT_SUCCESS;
}

对于我来说,它正常工作,mutt 1.6.1并且如您所见%,如果这是真正的问题所在,那么签入主题没有任何问题:在此处输入图片说明

这是最初的“正常工作”版本,因为仔细查看了您的原始问题后,我不确定这是否是您想要的。但是,如果这你想要让我知道什么,我们会考虑如何更好地做到这一点。

编辑

它也可以与您的首选一起使用index_format

set index_format='mfdate "%[%s]" "%%Z %%{%%Y %%b %%e  %%H:%%M} %%?X?(%%X)&   ? %%-22.22F  %%.100s %%> %%5c" |'

mfdate.c:

#include <stdlib.h>
#include <stdio.h>
#include <time.h>

#define DAY (time_t)86400
#define YEAR (time_t)31556926

int main(int argc, const char *argv[]) {
  time_t current_time;
  time_t message_time;

  const char *old = "old";
  char *recent = "recent";
  char *today = "today";
  const char *format;

  current_time = time(NULL);

  if (argc != 3) {
    printf("Usage: %s format\n", argv[0]);
    return EXIT_FAILURE;
  }

  format = argv[2];

  message_time = atoi(argv[1]);

  if ((message_time/YEAR) < (current_time/YEAR)) {
    printf("%s,%s%%", old, format);
  } else if ((message_time/DAY) < (current_time/DAY)) {
    printf("%s,%s%%", recent, format);
  } else {
    printf("%s,%s%%", today, format);
  }

  return 0;
}

在此处输入图片说明

编辑

让我解释一下它是如何工作的:

mfdate需要两个参数:

"%[%s]"

和:

"%%Z %%{%%Y %%b %%e  %%H:%%M} %%?X?(%%X)&   ? %%-22.22F  %%.100s %%> %%5c"

第一个参数是only time of the message,如 index_format文档中所述.muttrc

# %[fmt]  the date and time of the message is converted to the local
#         time zone, and ``fmt'' is expanded by the library function
#         ``strftime''; a leading bang disables locales

在这种情况下fmt被替换为%s,因为中的%s方法The number of seconds since the Epoch如中所述man strftime。第一个参数是用来计算出有老的消息是什么标签:oldrecent或者today它应该有。

第二个参数是index_format 变量的其余部分。它在使用mfdate仅用于打印,但额外%在末尾添加printf因为它说傻子手册

返回的字符串将用于显示。如果返回的字符串以%结尾,它将再次通过格式化程序。

%此处每个元素都加倍,因为我们想将文字传递%给所完成的第二种格式mutt


为什么要下票?这个答案有什么问题吗?
Arkadiusz Drabczyk '17
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.