mutt: Bedingtes Datumsformat in "index_format"

13

Ich habe folgenden Wert für index_formatin Mutt festgelegt:

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

welches Datum im Format als anzeigt

2013 Dec 5

Ich habe mich gefragt, ob es je nach Alter der E-Mail möglich ist, unterschiedliche Datumsformate zu verwenden. Damit meine ich:

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

Ich glaube, ich habe diese Funktionalität in Thunderbird gesehen. Wäre schön es in mutt zu haben

Martin Vegter
quelle

Antworten:

15

Wenn Sie die "Entwicklungs" -Version von mutt (v1.5 +) verwenden - und das sollten Sie unbedingt -, besteht die Möglichkeit, einen externen Filter wie im Handbuch beschrieben zu verwenden .

Zuerst benötigen Sie ein Skript, das je nach Alter einer Nachricht unterschiedliche Dinge ausgeben kann. Hier ist ein Beispiel in 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))

Speichern Sie dies als mutt-fmt-dateirgendwo auf Ihrem Pfad.

Zwei Dinge sind hier wichtig:

  • Die Formatzeichenfolge muss ein Vorkommen enthalten, {}das durch den Rückgabewert age_fmt()von Python ersetzt wird.
  • Die Formatzeichenfolge muss mit einem enden, %damit Mutt sie interpretiert.

Dann können Sie es .muttrcwie folgt verwenden:

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

Mutt wird dann

  1. interpretiere %[%s]nach den Regeln für Formatstrings.
  2. Aufruf mutt-fmt-datemit dem Ergebnis von 1. als Argument (wegen der |am Ende).
  3. interpretiere, was es aus dem Skript zurückerhält, wieder als Formatstring (wegen der %am Ende).

Vorsichtsmaßnahme : Das Skript wird für jede Nachricht ausgeführt, die angezeigt werden soll. Die daraus resultierende Verzögerung kann beim Blättern durch eine Mailbox sehr auffällig sein.

Hier ist eine Version in C, die einigermaßen zufriedenstellend funktioniert:

#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;
}

Dies geht zusammen mit der muttrc-Zeile:

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

quelle
Ich hatte noch keine Zeit, dies zu debuggen, aber es scheint ein Problem mit dieser Lösung und Themen zu geben, die ein% -Zeichen enthalten. Patches wären willkommen!
1
Ich habe ein Kopfgeld geschaffen. Haben Sie Ideen, wie Sie den Fehler beheben können?
Martin Vegter
7

Leider scheint dies mit aktuellen Versionen von Mutt nicht möglich zu sein.

$index_formatunterstützt einen bestimmten Satz von Formatspezifizierern, die aus verschiedenen Nachrichtenmetadaten stammen. Es ist im Mutt-Handbuch beschrieben (oder hier ist die Dokumentation der "Stable" -Version ), und wie Sie aus der Tabelle ersehen können, gibt es nur wenige Formatspezifizierer, die bedingt sind. Das ist %M, %yund %Y; % M ist die Anzahl der ausgeblendeten Nachrichten, wenn der Thread ausgeblendet ist, und% y und% Y sind X-Label-Header, falls vorhanden.

Die eigentliche Formatierung des Datums und der Uhrzeit der Nachricht erfolgt durch strftime(3), wobei die bedingte Formatierung überhaupt nicht unterstützt wird.

Es könnte möglich sein, eine hässliche Lösung zu finden, indem die Date:Header der Nachrichtendateien ständig neu geschrieben werden , aber das würde ich zumindest nicht wollen. Es ist jedoch die am wenigsten schlechte Möglichkeit, die ich mir vorstellen kann.

Die einzige wirkliche Lösung, die ich mir strftimevorstellen kann, wäre, entweder eine solche Unterstützung in Mutt zu implementieren (wie Thunderbird es mit ziemlicher Sicherheit tut) oder eine Ersetzung zu schreiben , die bedingte Formatierungen unterstützt und diese mit LD_PRELOAD oder einem ähnlichen Mechanismus einfügt. Letzteres wirkt sich jedoch nicht nur auf den Nachrichtenindex aus , sondern auch auf die gesamte Datums- und Uhrzeitanzeige in Mutt, die durch die Arbeitszeit geht.

ein CVn
quelle
2
Wenn Sie Version 1.5+ verwenden (was Sie unbedingt sollten), gibt es einen Weg. Der Vorschlag, die
@hop FWIW, deine Antwort wurde positiv bewertet.
ein Lebenslauf
4

Aus irgendeinem Grund haben neuere Versionen von mutt (1.7 dieses Problem gezeigt) dem Datumsstring die Zeichen '14' und '32' vorangestellt, die atoi davon abhalten, den String in ein int zu konvertieren. Ändern der Zeile in

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

Möglicherweise eine blöde Lösung, aber es funktioniert bei mir.

Marcus H
quelle
4

@Marcus 'c-Version etwas überarbeitet (allerdings noch keine Lösung für das %im Betreff angegebene Problem):

// -*- 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;
}

Dieses Format ist wie folgt datiert (alle Zeiten sind im 24-Stunden-Format):

  • 02:04 für die heutige Mail
  • ydy 02:04 für die gestrige Mail
  • Thu 02:04 für die letzten 7 Tage mail
  • 27.Mar für die Post des laufenden Jahres
  • 13.12.16 für die Mail der Vorjahre

Das vollständige Indexformat in diesem Beispiel lautet #no [flags] #no_of_attachments date sender subject msg_size

laur
quelle
3

Es wurden einige Änderungen vorgenommen, das Problem "% im Betreff" wurde jedoch nicht behoben

#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;
}
Marcus H
quelle
Es wäre gut, wenn Sie die vorgenommenen Änderungen und die Gründe dafür zusammenfassen würden.
Zagrimsan
-1

Diese index_formatVariable

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

zusammen mit dieser modifizierten mfdate.cin dieser Antwort von Benutzer hop vorgestellt :

#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;
}

Funktioniert bei mir einwandfrei mutt 1.6.1und wie Sie sehen gibt es keine Probleme mit dem %Anmelden im Betreff, wenn dies das eigentliche Problem ist:Bildbeschreibung hier eingeben

Dies ist die erste "nur funktionierende" Version, denn nachdem ich mir Ihre ursprüngliche Frage genauer angesehen habe, bin ich mir nicht sicher, ob dies das ist, was Sie wollen. Wenn Sie dies jedoch möchten, lassen Sie es mich wissen und wir überlegen, wie wir es verbessern können.

EDIT :

Es kann auch mit Ihrem bevorzugten arbeiten 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;
}

Bildbeschreibung hier eingeben

EDIT :

Lassen Sie mich erklären, wie es funktioniert:

Das mfdatebraucht 2 Argumente:

"%[%s]"

und:

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

Das erste Argument ist nur time of the message, wie in der index_formatDokumentation in beschrieben .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

In diesem Fall fmtwird ersetzt durch %s, weil als %sMittel The number of seconds since the Epochwie in erläutert man strftime. Das erste Argument wird verwendet , wie alt zu berechnen die Nachricht ist und was Etikett: old, recentoder todayes haben sollte.

Das zweite Argument ist der verbleibende Teil der index_format Variablen. Es wird mfdatenur zum Drucken verwendet, aber %am Ende von wird ein zusätzliches hinzugefügt, printfweil, wie es im Handbuch von mutt steht :

Die zurückgegebene Zeichenfolge wird zur Anzeige verwendet. Wenn der zurückgegebene String mit% endet, wird er ein zweites Mal durch den Formatierer geleitet.

Jeder %wird hier verdoppelt, weil wir ein Literal %an die zweite Formatierung übergeben möchten, die von vorgenommen wird mutt.

Arkadiusz Drabczyk
quelle
Warum die Gegenstimme? Stimmt etwas mit dieser Antwort nicht?
Arkadiusz Drabczyk