mutt: format daty warunkowej w „formacie_indeksu”


15

Mam ustawioną następującą wartość dla index_formatmutt:

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

która wyświetla datę w formacie jako

2013 Dec 5

Zastanawiałem się, czy możliwe są różne formaty dat, w zależności od wieku e-maila. Rozumiem przez to:

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

Myślę, że widziałem tę funkcjonalność w Thunderbird. Byłoby miło mieć to w kundlu

Odpowiedzi:


16

Jeśli używasz „rozwojowej” wersji mutt (v1.5 +) - i absolutnie powinieneś - istnieje możliwość użycia zewnętrznego filtra, jak opisano w instrukcji .

Najpierw potrzebujesz skryptu, który może wypisywać różne rzeczy w zależności od wieku wiadomości. Oto przykład w Pythonie:

#!/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))

Zapisz to mutt-fmt-dategdzieś na swojej ŚCIEŻCE.

Ważne są tutaj dwie rzeczy:

  • Łańcuch formatu musi zawierać jedno wystąpienie, {}które zostanie zastąpione wartością zwracaną age_fmt()przez Python.
  • Ciąg formatu musi kończyć się znakiem %, aby Mutt go zinterpretował.

Następnie możesz użyć go w .muttrcnastępujący sposób:

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

Mutt to zrobi

  1. interpretować %[%s]zgodnie z regułami dla ciągów formatujących.
  2. wywołanie mutt-fmt-datez wynikiem 1. jako argumentem (ze względu |na koniec).
  3. interpretuje to, co otrzymuje ze skryptu, ponownie jako ciąg formatujący (ze względu %na koniec).

Uwaga : skrypt zostanie wykonany dla każdej wiadomości, która ma być wyświetlana. Wynikające z tego opóźnienie może być dość zauważalne podczas przewijania skrzynki pocztowej.

Oto wersja w C, która działa nieco odpowiednio:

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

Jest to zgodne z linią muttrc:

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

Nie miałem jeszcze czasu na debugowanie tego, ale wydaje się, że jest problem z tym rozwiązaniem i przedmiotami zawierającymi znak%. Poprawki będą mile widziane!

1
Stworzyłem nagrodę. Czy masz jakieś pomysły, jak naprawić błąd?
Martin Vegter,

7

Niestety nie wydaje się to możliwe w przypadku obecnych wersji Mutt.

$index_formatobsługuje określony zestaw specyfikatorów formatu, czerpiąc z różnych metadanych wiadomości. Jest to opisane w podręczniku Mutt (lub tutaj jest dokumentacja „stabilnej” wersji tego samego ), a jak widać z tabeli, istnieje tylko kilka specyfikatorów formatu, które są warunkowe. Są to %M, %yi %Y; % M to liczba ukrytych wiadomości, jeśli wątek jest zwinięty, a% y i% Y są nagłówkami X-Label, jeśli są obecne.

Rzeczywiste formatowanie daty i godziny wiadomości jest wykonywane przez strftime(3), co wcale nie obsługuje formatowania warunkowego.

To może być możliwe, aby zrobić brzydki obejścia poprzez ciągłe przepisywanie pliki komunikat Date:nagłówków, ale nie chcę tego robić przynajmniej. Jest to jednak najmniej zła możliwość, o której mogę myśleć.

Jedyne realne rozwiązanie, jakie mogę wymyślić, to albo zaimplementować taką obsługę w Mutt (co prawie na pewno robi to Thunderbird), albo napisać zamiennik, strftimektóry obsługuje formatowanie warunkowe i wstrzyknąć to za pomocą LD_PRELOAD lub podobnego mechanizmu. To ostatnie wpłynie jednak na wyświetlanie wszystkich dat i godzin w Mutt, które przechodzi przez strftime, nie tylko odnosząc się do indeksu komunikatów.


2
Jeśli używasz wersji 1.5+ (co absolutnie powinieneś), istnieje sposób. Sugerowanie przepisania nagłówków dat jest jednak przezabawne…

@hop FWIW, twoja odpowiedź uzyskała moje poparcie.
CVn

4

Z jakiegoś powodu nowsze wersje mutt (1.7 pokazały ten problem) poprzedzają łańcuch daty znakami „14” i „32”, które powstrzymują atoi przed konwersją łańcucha na wartość int. Zmiana linii na

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

Być może to głupie rozwiązanie, ale dla mnie działa.


4

Zmieniono nieco wersję @Marcus 'c (wciąż nie ma rozwiązania %w temacie tematu):

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

Formatuje daty w następujący sposób (wszystkie czasy są w formacie 24-godzinnym):

  • 02:04 dla dzisiejszej poczty
  • ydy 02:04 na wczorajszą pocztę
  • Thu 02:04 za ostatnie 7 dni poczta
  • 27.Mar na bieżący rok
  • 13.12.16 za pocztę z poprzednich lat

Pełny format indeksu w tym przykładzie to #no [flags] #no_of_attachments date sender subject msg_size


3

Wprowadzono pewne zmiany, ale nie rozwiązano problemu „% w temacie”

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

Byłoby dobrze, gdybyś podsumował dokonane zmiany i powody ich wprowadzenia.
zagrimsan

0

Ta index_formatzmienna

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

razem z tym zmodyfikowanym mfdate.cprezentowane w tej odpowiedzi przez użytkownika hop :

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

działa dla mnie poprawnie mutt 1.6.1i jak widzisz, nie ma problemów z %logowaniem się w temacie, jeśli o to właśnie chodziło:wprowadź opis zdjęcia tutaj

Jest to początkowa „tylko działająca” wersja, ponieważ po bliższym przyjrzeniu się pierwotnemu pytaniu nie jestem pewien, czy tego właśnie chcesz. Jednakże, jeśli to jest to, co chcesz dać mi znać i będziemy myśleć, jak zrobić to lepiej.

EDYCJA :

Może również działać z twoimi preferowanymi 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;
}

wprowadź opis zdjęcia tutaj

EDYCJA :

Pozwól mi wyjaśnić, jak to działa:

Przyjmuje mfdate2 argumenty:

"%[%s]"

i:

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

Pierwszy argument jest tylko time of the messageopisany w index_formatdokumentacji w .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

W tym przypadku fmtjest zastąpiony przez %s, ponieważ jako %sśrodki The number of seconds since the Epochwyjaśnione w man strftime. Pierwszy argument jest używany do obliczenia jak stary wiadomość jest i co etykietę: old, recentlub todaypowinien on mieć.

Drugi argument to pozostała część index_format zmiennej. Jest używany mfdatetylko do drukowania, ale %na końcu dodaje się dodatkowy, printfponieważ, jak mówi w podręczniku mutt :

Zwrócony ciąg zostanie użyty do wyświetlenia. Jeśli zwrócony ciąg kończy się na%, zostanie przekazany przez formatyzator po raz drugi.

Wszystko %jest tutaj podwojone, ponieważ chcemy przekazać literał %do drugiego formatowania wykonanego przez mutt.


Dlaczego głosowanie negatywne? Coś nie tak z tą odpowiedzią?
Arkadiusz Drabczyk
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.